diff --git a/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/AmmonitePhase.scala b/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/AmmonitePhase.scala
deleted file mode 100644
index 333645aa7..000000000
--- a/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/AmmonitePhase.scala
+++ /dev/null
@@ -1,264 +0,0 @@
-package ammonite.compiler
-
-import ammonite.util.{ImportData, Imports, Name => AmmName, Printer, Util}
-
-import dotty.tools.dotc
-import dotty.tools.dotc.core.StdNames.nme
-import dotc.ast.Trees._
-import dotc.ast.{tpd, untpd}
-import dotc.core.Flags
-import dotc.core.Contexts._
-import dotc.core.Names.Name
-import dotc.core.Phases.Phase
-import dotc.core.Symbols.{NoSymbol, Symbol, newSymbol}
-import dotc.core.Types.{TermRef, Type, TypeTraverser}
-
-import scala.collection.mutable
-
-class AmmonitePhase(
- userCodeNestingLevel: => Int,
- needsUsedEarlierDefinitions: => Boolean
-) extends Phase:
- import tpd._
-
- def phaseName: String = "ammonite"
-
- private var myImports = new mutable.ListBuffer[(Boolean, String, String, Seq[AmmName])]
- private var usedEarlierDefinitions0 = new mutable.ListBuffer[String]
-
- def importData: Seq[ImportData] =
- val grouped = myImports
- .toList
- .distinct
- .groupBy { case (a, b, c, d) => (b, c, d) }
- .mapValues(_.map(_._1))
-
- val open = for {
- ((fromName, toName, importString), items) <- grouped
- if !CompilerUtil.ignoredNames(fromName)
- } yield {
- val importType = items match{
- case Seq(true) => ImportData.Type
- case Seq(false) => ImportData.Term
- case Seq(_, _) => ImportData.TermType
- }
-
- ImportData(AmmName(fromName), AmmName(toName), importString, importType)
- }
-
- open.toVector.sortBy(x => Util.encodeScalaSourcePath(x.prefix))
-
- def usedEarlierDefinitions: Seq[String] =
- usedEarlierDefinitions0.toList.distinct
-
- private def saneSym(name: Name, sym: Symbol)(using Context): Boolean =
- !name.decode.toString.contains('$') &&
- sym.exists &&
- // !sym.is(Flags.Synthetic) &&
- !scala.util.Try(sym.is(Flags.Private)).toOption.getOrElse(true) &&
- !scala.util.Try(sym.is(Flags.Protected)).toOption.getOrElse(true) &&
- // sym.is(Flags.Public) &&
- !CompilerUtil.ignoredSyms(sym.toString) &&
- !CompilerUtil.ignoredNames(name.decode.toString)
-
- private def saneSym(sym: Symbol)(using Context): Boolean =
- saneSym(sym.name, sym)
-
- private def processTree(t: tpd.Tree)(using Context): Unit = {
- val sym = t.symbol
- val name = t match {
- case t: tpd.ValDef => t.name
- case _ => sym.name
- }
- if (saneSym(name, sym)) {
- val name = sym.name.decode.toString
- myImports.addOne((sym.isType, name, name, Nil))
- }
- }
-
- private def processImport(i: tpd.Import)(using Context): Unit = {
- val expr = i.expr
- val selectors = i.selectors
-
- // Most of that logic was adapted from AmmonitePlugin, the Scala 2 counterpart
- // of this file.
-
- val prefix =
- val (_ :: nameListTail, symbolHead :: _) = {
- def rec(expr: tpd.Tree): List[(Name, Symbol)] = {
- expr match {
- case s @ tpd.Select(lhs, _) => (s.symbol.name -> s.symbol) :: rec(lhs)
- case i @ tpd.Ident(name) => List(name -> i.symbol)
- case t @ tpd.This(pkg) => List(pkg.name -> t.symbol)
- }
- }
- rec(expr).reverse.unzip
- }
-
- val headFullPath = symbolHead.fullName.decode.toString.split('.')
- .map(n => if (n.endsWith("$")) n.stripSuffix("$") else n) // meh
- // prefix package imports with `_root_` to try and stop random
- // variables from interfering with them. If someone defines a value
- // called `_root_`, this will still break, but that's their problem
- val rootPrefix = if(symbolHead.denot.is(Flags.Package)) Seq("_root_") else Nil
- val tailPath = nameListTail.map(_.decode.toString)
-
- (rootPrefix ++ headFullPath ++ tailPath).map(AmmName(_))
-
- def isMask(sel: untpd.ImportSelector) = sel.name != nme.WILDCARD && sel.rename == nme.WILDCARD
-
- val renameMap =
-
- /**
- * A map of each name importable from `expr`, to a `Seq[Boolean]`
- * containing a `true` if there's a type-symbol you can import, `false`
- * if there's a non-type symbol and both if there are both type and
- * non-type symbols that are importable for that name
- */
- val importableIsTypes =
- expr.tpe
- .allMembers
- .map(_.symbol)
- .filter(saneSym(_))
- .groupBy(_.name.decode.toString)
- .mapValues(_.map(_.isType).toVector)
-
- val renamings = for{
- t @ untpd.ImportSelector(name, renameTree, _) <- selectors
- if !isMask(t)
- // getOrElse just in case...
- isType <- importableIsTypes.getOrElse(name.name.decode.toString, Nil)
- Ident(rename) <- Option(renameTree)
- } yield ((isType, rename.decode.toString), name.name.decode.toString)
-
- renamings.toMap
-
-
- def isUnimportableUnlessRenamed(sym: Symbol): Boolean =
- sym eq NoSymbol
-
- @scala.annotation.tailrec
- def transformImport(selectors: List[untpd.ImportSelector], sym: Symbol): List[Symbol] =
- selectors match {
- case Nil => Nil
- case sel :: Nil if sel.isWildcard =>
- if (isUnimportableUnlessRenamed(sym)) Nil
- else List(sym)
- case (sel @ untpd.ImportSelector(from, to, _)) :: _
- if from.name == (if (from.isTerm) sym.name.toTermName else sym.name.toTypeName) =>
- if (isMask(sel)) Nil
- else List(
- newSymbol(sym.owner, sel.rename, sym.flags, sym.info, sym.privateWithin, sym.coord)
- )
- case _ :: rest => transformImport(rest, sym)
- }
-
- val symNames =
- for {
- sym <- expr.tpe.allMembers.map(_.symbol).flatMap(transformImport(selectors, _))
- if saneSym(sym)
- } yield (sym.isType, sym.name.decode.toString)
-
- val syms = for {
- // For some reason `info.allImportedSymbols` does not show imported
- // type aliases when they are imported directly e.g.
- //
- // import scala.reflect.macros.Context
- //
- // As opposed to via import scala.reflect.macros._.
- // Thus we need to combine allImportedSymbols with the renameMap
- (isType, sym) <- (symNames.toList ++ renameMap.keys).distinct
- } yield (isType, renameMap.getOrElse((isType, sym), sym), sym, prefix)
-
- myImports ++= syms
- }
-
- private def updateUsedEarlierDefinitions(
- wrapperSym: Symbol,
- stats: List[tpd.Tree]
- )(using Context): Unit = {
- /*
- * We list the variables from the first wrapper
- * used from the user code.
- *
- * E.g. if, after wrapping, the code looks like
- * ```
- * class cmd2 {
- *
- * val cmd0 = ???
- * val cmd1 = ???
- *
- * import cmd0.{
- * n
- * }
- *
- * class Helper {
- * // user-typed code
- * val n0 = n + 1
- * }
- * }
- * ```
- * this would process the tree of `val n0 = n + 1`, find `n` as a tree like
- * `cmd2.this.cmd0.n`, and put `cmd0` in `uses`.
- */
-
- val typeTraverser: TypeTraverser = new TypeTraverser {
- def traverse(tpe: Type) = tpe match {
- case tr: TermRef if tr.prefix.typeSymbol == wrapperSym =>
- tr.designator match {
- case n: Name => usedEarlierDefinitions0 += n.decode.toString
- case s: Symbol => usedEarlierDefinitions0 += s.name.decode.toString
- case _ => // can this happen?
- }
- case _ =>
- traverseChildren(tpe)
- }
- }
-
- val traverser: TreeTraverser = new TreeTraverser {
- def traverse(tree: Tree)(using Context) = tree match {
- case tpd.Select(node, name) if node.symbol == wrapperSym =>
- usedEarlierDefinitions0 += name.decode.toString
- case tt @ tpd.TypeTree() =>
- typeTraverser.traverse(tt.tpe)
- case _ =>
- traverseChildren(tree)
- }
- }
-
- for (tree <- stats)
- traverser.traverse(tree)
- }
-
- private def unpkg(tree: tpd.Tree): List[tpd.Tree] =
- tree match {
- case PackageDef(_, elems) => elems.flatMap(unpkg)
- case _ => List(tree)
- }
-
- def run(using Context): Unit =
- val elems = unpkg(ctx.compilationUnit.tpdTree)
- def mainStats(trees: List[tpd.Tree]): List[tpd.Tree] =
- trees
- .reverseIterator
- .collectFirst {
- case TypeDef(name, rhs0: Template) => rhs0.body
- }
- .getOrElse(Nil)
-
- val rootStats = mainStats(elems)
- val stats = (1 until userCodeNestingLevel)
- .foldLeft(rootStats)((trees, _) => mainStats(trees))
-
- if (needsUsedEarlierDefinitions) {
- val wrapperSym = elems.last.symbol
- updateUsedEarlierDefinitions(wrapperSym, stats)
- }
-
- stats.foreach {
- case i: Import => processImport(i)
- case t: tpd.DefDef => processTree(t)
- case t: tpd.ValDef => processTree(t)
- case t: tpd.TypeDef => processTree(t)
- case _ =>
- }
diff --git a/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/Preprocessor.scala b/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/Preprocessor.scala
deleted file mode 100644
index 273005258..000000000
--- a/amm/compiler/src/main/scala-3.0.0-3.3.1/ammonite/compiler/Preprocessor.scala
+++ /dev/null
@@ -1,332 +0,0 @@
-package ammonite.compiler
-
-import java.util.function.{Function => JFunction}
-
-import ammonite.compiler.iface.{Compiler => _, Parser => _, Preprocessor => IPreprocessor, _}
-import ammonite.util.{Imports, Name, Res}
-import ammonite.util.Util.CodeSource
-import pprint.Util
-
-import dotty.tools.dotc
-import dotc.ast.desugar
-import dotc.ast.untpd
-import dotc.core.Contexts._
-import dotc.core.{Flags, Names}
-import dotc.parsing.Parsers.Parser
-import dotc.parsing.Tokens
-import dotc.util.SourceFile
-
-class Preprocessor(
- ctx: Context,
- markGeneratedSections: Boolean
-) extends IPreprocessor {
-
- // FIXME Quite some duplication with DefaultProcessor for Scala 2.x
-
- private case class Expanded(code: String, printer: Seq[String])
-
- private def parse(source: String): Either[Seq[String], List[untpd.Tree]] = {
- val reporter = Compiler.newStoreReporter()
- val sourceFile = SourceFile.virtual("foo", source)
- val parseCtx = ctx.fresh.setReporter(reporter).withSource(sourceFile)
- val parser = new DottyParser(sourceFile)(using parseCtx)
- val stats = parser.blockStatSeq()
- parser.accept(Tokens.EOF)
- if (reporter.hasErrors) {
- val errorsStr = reporter
- .allErrors
- // .map(rendering.formatError)
- .map(e => scala.util.Try(e.msg.toString).toOption.getOrElse("???"))
- Left(errorsStr)
- } else
- Right(stats)
- }
-
- def transform(
- stmts: Seq[String],
- resultIndex: String,
- leadingSpaces: String,
- codeSource: CodeSource,
- indexedWrapper: Name,
- imports: Imports,
- printerTemplate: String => String,
- extraCode: String,
- skipEmpty: Boolean,
- markScript: Boolean,
- codeWrapper: CodeWrapper
- ): Res[IPreprocessor.Output] = {
-
- // println(s"transformOrNull(${stmts.toSeq})")
-
- // All code Ammonite compiles must be rooted in some package within
- // the `ammonite` top-level package
- assert(codeSource.pkgName.head == Name("ammonite"))
-
- expandStatements(stmts, resultIndex, skipEmpty).map {
- case Expanded(code, printer) =>
- val (wrappedCode, importsLength, userCodeNestingLevel) = wrapCode(
- codeSource, indexedWrapper, leadingSpaces + code,
- printerTemplate(printer.mkString(", ")),
- imports, extraCode, markScript, codeWrapper
- )
- IPreprocessor.Output(wrappedCode, importsLength, userCodeNestingLevel)
- }
- }
-
- private def expandStatements(
- stmts: Seq[String],
- wrapperIndex: String,
- skipEmpty: Boolean
- ): Res[Expanded] =
- stmts match{
- // In the REPL, we do not process empty inputs at all, to avoid
- // unnecessarily incrementing the command counter
- //
- // But in scripts, we process empty inputs and create an empty object,
- // to ensure that when the time comes to cache/load the class it exists
- case Nil if skipEmpty => Res.Skip
- case postSplit =>
- Res(complete(stmts.mkString(""), wrapperIndex, postSplit))
-
- }
-
- private def wrapCode(
- codeSource: CodeSource,
- indexedWrapperName: Name,
- code: String,
- printCode: String,
- imports: Imports,
- extraCode: String,
- markScript: Boolean,
- codeWrapper: CodeWrapper
- ) = {
-
- //we need to normalize topWrapper and bottomWrapper in order to ensure
- //the snippets always use the platform-specific newLine
- val extraCode0 =
- if (markScript) extraCode + "/**/"
- else extraCode
- val (topWrapper, bottomWrapper, userCodeNestingLevel) =
- codeWrapper(code, codeSource, imports, printCode, indexedWrapperName, extraCode0)
- val (topWrapper0, bottomWrapper0) =
- if (markScript) (topWrapper + "/**/ /**/" + bottomWrapper)
- else (topWrapper, bottomWrapper)
- val importsLen = topWrapper0.length
-
- (topWrapper0 + code + bottomWrapper0, importsLen, userCodeNestingLevel)
- }
-
- // Large parts of the logic below is adapted from DefaultProcessor,
- // the Scala 2 counterpart of this file.
-
- private def isPrivate(tree: untpd.Tree): Boolean =
- tree match {
- case m: untpd.MemberDef => m.mods.is(Flags.Private)
- case _ => false
- }
-
- private def Processor(cond: PartialFunction[(String, String, untpd.Tree), Expanded]) =
- (code: String, name: String, tree: untpd.Tree) => cond.lift(name, code, tree)
-
- private def pprintSignature(ident: String, customMsg: Option[String]): String =
- val customCode = customMsg.fold("_root_.scala.None")(x => s"""_root_.scala.Some("$x")""")
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .print($ident, ${Util.literalize(ident)}, $customCode)
- """
- private def definedStr(definitionLabel: String, name: String) =
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .printDef("$definitionLabel", ${Util.literalize(name)})
- """
- private def pprint(ident: String) = pprintSignature(ident, None)
-
- /**
- * Processors for declarations which all have the same shape
- */
- private def DefProc(definitionLabel: String)(cond: PartialFunction[untpd.Tree, Names.Name]) =
- (code: String, name: String, tree: untpd.Tree) =>
- cond.lift(tree).map{ name =>
- val printer =
- if (isPrivate(tree)) Nil
- else
- val definedName =
- if name.isEmpty then ""
- else Name.backtickWrap(name.decode.toString)
- Seq(definedStr(definitionLabel, definedName))
- Expanded(
- code,
- printer
- )
- }
-
- private val ObjectDef = DefProc("object"){case m: untpd.ModuleDef => m.name}
- private val ClassDef = DefProc("class"){
- case m: untpd.TypeDef if m.isClassDef && !m.mods.flags.is(Flags.Trait) =>
- m.name
- }
- private val TraitDef = DefProc("trait"){
- case m: untpd.TypeDef if m.isClassDef && m.mods.flags.is(Flags.Trait) =>
- m.name
- }
- private val DefDef = DefProc("function"){
- case m: untpd.DefDef if m.mods.flags.is(Flags.Given) && m.name.isEmpty =>
- given Context = ctx
- desugar.inventGivenOrExtensionName(m.tpt)
- case m: untpd.DefDef =>
- m.name
- }
-
- private val ExtDef = DefProc("extension methods") {
- case ext: untpd.ExtMethods => Names.EmptyTermName
- }
- private val TypeDef = DefProc("type"){ case m: untpd.TypeDef => m.name }
-
- private val VarDef = Processor { case (name, code, t: untpd.ValDef) =>
- Expanded(
- //Only wrap rhs in function if it is not a function
- //Wrapping functions causes type inference errors.
- code,
- // Try to leave out all synthetics; we don't actually have proper
- // synthetic flags right now, because we're dumb-parsing it and not putting
- // it through a full compilation
- if (isPrivate(t) || t.name.decode.toString.contains("$")) Nil
- else if (t.mods.flags.is(Flags.Given)) {
- given Context = ctx
- val name0 = if (t.name.isEmpty) desugar.inventGivenOrExtensionName(t.tpt) else t.name
- Seq(pprintSignature(Name.backtickWrap(name0.decode.toString), Some("")))
- }
- else if (t.mods.flags.is(Flags.Lazy))
- Seq(pprintSignature(Name.backtickWrap(t.name.decode.toString), Some("")))
- else Seq(pprint(Name.backtickWrap(t.name.decode.toString)))
- )
- }
-
- private val PatDef = Processor { case (name, code, t: untpd.PatDef) =>
- val isLazy = t.mods.flags.is(Flags.Lazy)
- val printers =
- if (isPrivate(t)) Nil
- else
- t.pats
- .flatMap {
- case untpd.Tuple(trees) => trees
- case elem => List(elem)
- }
- .flatMap {
- case untpd.Ident(name) =>
- val decoded = name.decode.toString
- if (decoded.contains("$")) Nil
- else if (isLazy) Seq(pprintSignature(Name.backtickWrap(decoded), Some("")))
- else Seq(pprint(Name.backtickWrap(decoded)))
- case _ => Nil // can this happen?
- }
- Expanded(code, printers)
- }
-
- private val Import = Processor {
- case (name, code, tree: untpd.Import) =>
- val Array(keyword, body) = code.split(" ", 2)
- val tq = "\"\"\""
- Expanded(code, Seq(
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .printImport(${Util.literalize(body)})
- """
- ))
- }
-
- private val Expr = Processor {
- //Expressions are lifted to anon function applications so they will be JITed
- case (name, code, tree) =>
- val expandedCode =
- if (markGeneratedSections)
- s"/**/val $name = /**/$code"
- else
- s"val $name = $code"
- Expanded(
- expandedCode,
- if (isPrivate(tree)) Nil else Seq(pprint(name))
- )
- }
-
- private val decls = Seq[(String, String, untpd.Tree) => Option[Expanded]](
- ObjectDef, ClassDef, TraitDef, DefDef, ExtDef, TypeDef, VarDef, PatDef, Import, Expr
- )
-
- private def complete(
- code: String,
- resultIndex: String,
- postSplit: Seq[String]
- ): Either[String, Expanded] = {
- val reParsed = postSplit.map(p => (parse(p), p))
- val errors = reParsed.collect{case (Left(e), _) => e }.flatten
- if (errors.length != 0) Left(errors.mkString(System.lineSeparator()))
- else {
- val allDecls = for {
- ((Right(trees), code), i) <- reParsed.zipWithIndex if trees.nonEmpty
- } yield {
- // Suffix the name of the result variable with the index of
- // the tree if there is more than one statement in this command
- val suffix = if (reParsed.length > 1) "_" + i else ""
- def handleTree(t: untpd.Tree) = {
- // println(s"handleTree($t)")
- val it = decls.iterator.flatMap(_.apply(code, "res" + resultIndex + suffix, t))
- if (it.hasNext)
- it.next()
- else {
- sys.error(s"Don't know how to handle ${t.getClass}: $t")
- }
- }
- trees match {
- case Seq(tree) => handleTree(tree)
-
- // This handles the multi-import case `import a.b, c.d`
- case trees if trees.forall(_.isInstanceOf[untpd.Import]) => handleTree(trees(0))
-
- // AFAIK this can only happen for pattern-matching multi-assignment,
- // which for some reason parse into a list of statements. In such a
- // scenario, aggregate all their printers, but only output the code once
- case trees =>
- val printers = for {
- tree <- trees
- if tree.isInstanceOf[untpd.ValDef]
- Expanded(_, printers) = handleTree(tree)
- printer <- printers
- } yield printer
-
- Expanded(code, printers)
- }
- }
-
- val expanded = allDecls match{
- case Seq(first, rest@_*) =>
- val allDeclsWithComments = Expanded(first.code, first.printer) +: rest
- allDeclsWithComments.reduce { (a, b) =>
- Expanded(
- // We do not need to separate the code with our own semi-colons
- // or newlines, as each expanded code snippet itself comes with
- // it's own trailing newline/semicolons as a result of the
- // initial split
- a.code + b.code,
- a.printer ++ b.printer
- )
- }
- case Nil => Expanded("", Nil)
- }
-
- Right(expanded)
- }
- }
-}
diff --git a/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/AmmonitePhase.scala b/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/AmmonitePhase.scala
deleted file mode 100644
index 333645aa7..000000000
--- a/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/AmmonitePhase.scala
+++ /dev/null
@@ -1,264 +0,0 @@
-package ammonite.compiler
-
-import ammonite.util.{ImportData, Imports, Name => AmmName, Printer, Util}
-
-import dotty.tools.dotc
-import dotty.tools.dotc.core.StdNames.nme
-import dotc.ast.Trees._
-import dotc.ast.{tpd, untpd}
-import dotc.core.Flags
-import dotc.core.Contexts._
-import dotc.core.Names.Name
-import dotc.core.Phases.Phase
-import dotc.core.Symbols.{NoSymbol, Symbol, newSymbol}
-import dotc.core.Types.{TermRef, Type, TypeTraverser}
-
-import scala.collection.mutable
-
-class AmmonitePhase(
- userCodeNestingLevel: => Int,
- needsUsedEarlierDefinitions: => Boolean
-) extends Phase:
- import tpd._
-
- def phaseName: String = "ammonite"
-
- private var myImports = new mutable.ListBuffer[(Boolean, String, String, Seq[AmmName])]
- private var usedEarlierDefinitions0 = new mutable.ListBuffer[String]
-
- def importData: Seq[ImportData] =
- val grouped = myImports
- .toList
- .distinct
- .groupBy { case (a, b, c, d) => (b, c, d) }
- .mapValues(_.map(_._1))
-
- val open = for {
- ((fromName, toName, importString), items) <- grouped
- if !CompilerUtil.ignoredNames(fromName)
- } yield {
- val importType = items match{
- case Seq(true) => ImportData.Type
- case Seq(false) => ImportData.Term
- case Seq(_, _) => ImportData.TermType
- }
-
- ImportData(AmmName(fromName), AmmName(toName), importString, importType)
- }
-
- open.toVector.sortBy(x => Util.encodeScalaSourcePath(x.prefix))
-
- def usedEarlierDefinitions: Seq[String] =
- usedEarlierDefinitions0.toList.distinct
-
- private def saneSym(name: Name, sym: Symbol)(using Context): Boolean =
- !name.decode.toString.contains('$') &&
- sym.exists &&
- // !sym.is(Flags.Synthetic) &&
- !scala.util.Try(sym.is(Flags.Private)).toOption.getOrElse(true) &&
- !scala.util.Try(sym.is(Flags.Protected)).toOption.getOrElse(true) &&
- // sym.is(Flags.Public) &&
- !CompilerUtil.ignoredSyms(sym.toString) &&
- !CompilerUtil.ignoredNames(name.decode.toString)
-
- private def saneSym(sym: Symbol)(using Context): Boolean =
- saneSym(sym.name, sym)
-
- private def processTree(t: tpd.Tree)(using Context): Unit = {
- val sym = t.symbol
- val name = t match {
- case t: tpd.ValDef => t.name
- case _ => sym.name
- }
- if (saneSym(name, sym)) {
- val name = sym.name.decode.toString
- myImports.addOne((sym.isType, name, name, Nil))
- }
- }
-
- private def processImport(i: tpd.Import)(using Context): Unit = {
- val expr = i.expr
- val selectors = i.selectors
-
- // Most of that logic was adapted from AmmonitePlugin, the Scala 2 counterpart
- // of this file.
-
- val prefix =
- val (_ :: nameListTail, symbolHead :: _) = {
- def rec(expr: tpd.Tree): List[(Name, Symbol)] = {
- expr match {
- case s @ tpd.Select(lhs, _) => (s.symbol.name -> s.symbol) :: rec(lhs)
- case i @ tpd.Ident(name) => List(name -> i.symbol)
- case t @ tpd.This(pkg) => List(pkg.name -> t.symbol)
- }
- }
- rec(expr).reverse.unzip
- }
-
- val headFullPath = symbolHead.fullName.decode.toString.split('.')
- .map(n => if (n.endsWith("$")) n.stripSuffix("$") else n) // meh
- // prefix package imports with `_root_` to try and stop random
- // variables from interfering with them. If someone defines a value
- // called `_root_`, this will still break, but that's their problem
- val rootPrefix = if(symbolHead.denot.is(Flags.Package)) Seq("_root_") else Nil
- val tailPath = nameListTail.map(_.decode.toString)
-
- (rootPrefix ++ headFullPath ++ tailPath).map(AmmName(_))
-
- def isMask(sel: untpd.ImportSelector) = sel.name != nme.WILDCARD && sel.rename == nme.WILDCARD
-
- val renameMap =
-
- /**
- * A map of each name importable from `expr`, to a `Seq[Boolean]`
- * containing a `true` if there's a type-symbol you can import, `false`
- * if there's a non-type symbol and both if there are both type and
- * non-type symbols that are importable for that name
- */
- val importableIsTypes =
- expr.tpe
- .allMembers
- .map(_.symbol)
- .filter(saneSym(_))
- .groupBy(_.name.decode.toString)
- .mapValues(_.map(_.isType).toVector)
-
- val renamings = for{
- t @ untpd.ImportSelector(name, renameTree, _) <- selectors
- if !isMask(t)
- // getOrElse just in case...
- isType <- importableIsTypes.getOrElse(name.name.decode.toString, Nil)
- Ident(rename) <- Option(renameTree)
- } yield ((isType, rename.decode.toString), name.name.decode.toString)
-
- renamings.toMap
-
-
- def isUnimportableUnlessRenamed(sym: Symbol): Boolean =
- sym eq NoSymbol
-
- @scala.annotation.tailrec
- def transformImport(selectors: List[untpd.ImportSelector], sym: Symbol): List[Symbol] =
- selectors match {
- case Nil => Nil
- case sel :: Nil if sel.isWildcard =>
- if (isUnimportableUnlessRenamed(sym)) Nil
- else List(sym)
- case (sel @ untpd.ImportSelector(from, to, _)) :: _
- if from.name == (if (from.isTerm) sym.name.toTermName else sym.name.toTypeName) =>
- if (isMask(sel)) Nil
- else List(
- newSymbol(sym.owner, sel.rename, sym.flags, sym.info, sym.privateWithin, sym.coord)
- )
- case _ :: rest => transformImport(rest, sym)
- }
-
- val symNames =
- for {
- sym <- expr.tpe.allMembers.map(_.symbol).flatMap(transformImport(selectors, _))
- if saneSym(sym)
- } yield (sym.isType, sym.name.decode.toString)
-
- val syms = for {
- // For some reason `info.allImportedSymbols` does not show imported
- // type aliases when they are imported directly e.g.
- //
- // import scala.reflect.macros.Context
- //
- // As opposed to via import scala.reflect.macros._.
- // Thus we need to combine allImportedSymbols with the renameMap
- (isType, sym) <- (symNames.toList ++ renameMap.keys).distinct
- } yield (isType, renameMap.getOrElse((isType, sym), sym), sym, prefix)
-
- myImports ++= syms
- }
-
- private def updateUsedEarlierDefinitions(
- wrapperSym: Symbol,
- stats: List[tpd.Tree]
- )(using Context): Unit = {
- /*
- * We list the variables from the first wrapper
- * used from the user code.
- *
- * E.g. if, after wrapping, the code looks like
- * ```
- * class cmd2 {
- *
- * val cmd0 = ???
- * val cmd1 = ???
- *
- * import cmd0.{
- * n
- * }
- *
- * class Helper {
- * // user-typed code
- * val n0 = n + 1
- * }
- * }
- * ```
- * this would process the tree of `val n0 = n + 1`, find `n` as a tree like
- * `cmd2.this.cmd0.n`, and put `cmd0` in `uses`.
- */
-
- val typeTraverser: TypeTraverser = new TypeTraverser {
- def traverse(tpe: Type) = tpe match {
- case tr: TermRef if tr.prefix.typeSymbol == wrapperSym =>
- tr.designator match {
- case n: Name => usedEarlierDefinitions0 += n.decode.toString
- case s: Symbol => usedEarlierDefinitions0 += s.name.decode.toString
- case _ => // can this happen?
- }
- case _ =>
- traverseChildren(tpe)
- }
- }
-
- val traverser: TreeTraverser = new TreeTraverser {
- def traverse(tree: Tree)(using Context) = tree match {
- case tpd.Select(node, name) if node.symbol == wrapperSym =>
- usedEarlierDefinitions0 += name.decode.toString
- case tt @ tpd.TypeTree() =>
- typeTraverser.traverse(tt.tpe)
- case _ =>
- traverseChildren(tree)
- }
- }
-
- for (tree <- stats)
- traverser.traverse(tree)
- }
-
- private def unpkg(tree: tpd.Tree): List[tpd.Tree] =
- tree match {
- case PackageDef(_, elems) => elems.flatMap(unpkg)
- case _ => List(tree)
- }
-
- def run(using Context): Unit =
- val elems = unpkg(ctx.compilationUnit.tpdTree)
- def mainStats(trees: List[tpd.Tree]): List[tpd.Tree] =
- trees
- .reverseIterator
- .collectFirst {
- case TypeDef(name, rhs0: Template) => rhs0.body
- }
- .getOrElse(Nil)
-
- val rootStats = mainStats(elems)
- val stats = (1 until userCodeNestingLevel)
- .foldLeft(rootStats)((trees, _) => mainStats(trees))
-
- if (needsUsedEarlierDefinitions) {
- val wrapperSym = elems.last.symbol
- updateUsedEarlierDefinitions(wrapperSym, stats)
- }
-
- stats.foreach {
- case i: Import => processImport(i)
- case t: tpd.DefDef => processTree(t)
- case t: tpd.ValDef => processTree(t)
- case t: tpd.TypeDef => processTree(t)
- case _ =>
- }
diff --git a/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/Preprocessor.scala b/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/Preprocessor.scala
deleted file mode 100644
index 273005258..000000000
--- a/amm/compiler/src/main/scala-3.3.2+/ammonite/compiler/Preprocessor.scala
+++ /dev/null
@@ -1,332 +0,0 @@
-package ammonite.compiler
-
-import java.util.function.{Function => JFunction}
-
-import ammonite.compiler.iface.{Compiler => _, Parser => _, Preprocessor => IPreprocessor, _}
-import ammonite.util.{Imports, Name, Res}
-import ammonite.util.Util.CodeSource
-import pprint.Util
-
-import dotty.tools.dotc
-import dotc.ast.desugar
-import dotc.ast.untpd
-import dotc.core.Contexts._
-import dotc.core.{Flags, Names}
-import dotc.parsing.Parsers.Parser
-import dotc.parsing.Tokens
-import dotc.util.SourceFile
-
-class Preprocessor(
- ctx: Context,
- markGeneratedSections: Boolean
-) extends IPreprocessor {
-
- // FIXME Quite some duplication with DefaultProcessor for Scala 2.x
-
- private case class Expanded(code: String, printer: Seq[String])
-
- private def parse(source: String): Either[Seq[String], List[untpd.Tree]] = {
- val reporter = Compiler.newStoreReporter()
- val sourceFile = SourceFile.virtual("foo", source)
- val parseCtx = ctx.fresh.setReporter(reporter).withSource(sourceFile)
- val parser = new DottyParser(sourceFile)(using parseCtx)
- val stats = parser.blockStatSeq()
- parser.accept(Tokens.EOF)
- if (reporter.hasErrors) {
- val errorsStr = reporter
- .allErrors
- // .map(rendering.formatError)
- .map(e => scala.util.Try(e.msg.toString).toOption.getOrElse("???"))
- Left(errorsStr)
- } else
- Right(stats)
- }
-
- def transform(
- stmts: Seq[String],
- resultIndex: String,
- leadingSpaces: String,
- codeSource: CodeSource,
- indexedWrapper: Name,
- imports: Imports,
- printerTemplate: String => String,
- extraCode: String,
- skipEmpty: Boolean,
- markScript: Boolean,
- codeWrapper: CodeWrapper
- ): Res[IPreprocessor.Output] = {
-
- // println(s"transformOrNull(${stmts.toSeq})")
-
- // All code Ammonite compiles must be rooted in some package within
- // the `ammonite` top-level package
- assert(codeSource.pkgName.head == Name("ammonite"))
-
- expandStatements(stmts, resultIndex, skipEmpty).map {
- case Expanded(code, printer) =>
- val (wrappedCode, importsLength, userCodeNestingLevel) = wrapCode(
- codeSource, indexedWrapper, leadingSpaces + code,
- printerTemplate(printer.mkString(", ")),
- imports, extraCode, markScript, codeWrapper
- )
- IPreprocessor.Output(wrappedCode, importsLength, userCodeNestingLevel)
- }
- }
-
- private def expandStatements(
- stmts: Seq[String],
- wrapperIndex: String,
- skipEmpty: Boolean
- ): Res[Expanded] =
- stmts match{
- // In the REPL, we do not process empty inputs at all, to avoid
- // unnecessarily incrementing the command counter
- //
- // But in scripts, we process empty inputs and create an empty object,
- // to ensure that when the time comes to cache/load the class it exists
- case Nil if skipEmpty => Res.Skip
- case postSplit =>
- Res(complete(stmts.mkString(""), wrapperIndex, postSplit))
-
- }
-
- private def wrapCode(
- codeSource: CodeSource,
- indexedWrapperName: Name,
- code: String,
- printCode: String,
- imports: Imports,
- extraCode: String,
- markScript: Boolean,
- codeWrapper: CodeWrapper
- ) = {
-
- //we need to normalize topWrapper and bottomWrapper in order to ensure
- //the snippets always use the platform-specific newLine
- val extraCode0 =
- if (markScript) extraCode + "/**/"
- else extraCode
- val (topWrapper, bottomWrapper, userCodeNestingLevel) =
- codeWrapper(code, codeSource, imports, printCode, indexedWrapperName, extraCode0)
- val (topWrapper0, bottomWrapper0) =
- if (markScript) (topWrapper + "/**/ /**/" + bottomWrapper)
- else (topWrapper, bottomWrapper)
- val importsLen = topWrapper0.length
-
- (topWrapper0 + code + bottomWrapper0, importsLen, userCodeNestingLevel)
- }
-
- // Large parts of the logic below is adapted from DefaultProcessor,
- // the Scala 2 counterpart of this file.
-
- private def isPrivate(tree: untpd.Tree): Boolean =
- tree match {
- case m: untpd.MemberDef => m.mods.is(Flags.Private)
- case _ => false
- }
-
- private def Processor(cond: PartialFunction[(String, String, untpd.Tree), Expanded]) =
- (code: String, name: String, tree: untpd.Tree) => cond.lift(name, code, tree)
-
- private def pprintSignature(ident: String, customMsg: Option[String]): String =
- val customCode = customMsg.fold("_root_.scala.None")(x => s"""_root_.scala.Some("$x")""")
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .print($ident, ${Util.literalize(ident)}, $customCode)
- """
- private def definedStr(definitionLabel: String, name: String) =
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .printDef("$definitionLabel", ${Util.literalize(name)})
- """
- private def pprint(ident: String) = pprintSignature(ident, None)
-
- /**
- * Processors for declarations which all have the same shape
- */
- private def DefProc(definitionLabel: String)(cond: PartialFunction[untpd.Tree, Names.Name]) =
- (code: String, name: String, tree: untpd.Tree) =>
- cond.lift(tree).map{ name =>
- val printer =
- if (isPrivate(tree)) Nil
- else
- val definedName =
- if name.isEmpty then ""
- else Name.backtickWrap(name.decode.toString)
- Seq(definedStr(definitionLabel, definedName))
- Expanded(
- code,
- printer
- )
- }
-
- private val ObjectDef = DefProc("object"){case m: untpd.ModuleDef => m.name}
- private val ClassDef = DefProc("class"){
- case m: untpd.TypeDef if m.isClassDef && !m.mods.flags.is(Flags.Trait) =>
- m.name
- }
- private val TraitDef = DefProc("trait"){
- case m: untpd.TypeDef if m.isClassDef && m.mods.flags.is(Flags.Trait) =>
- m.name
- }
- private val DefDef = DefProc("function"){
- case m: untpd.DefDef if m.mods.flags.is(Flags.Given) && m.name.isEmpty =>
- given Context = ctx
- desugar.inventGivenOrExtensionName(m.tpt)
- case m: untpd.DefDef =>
- m.name
- }
-
- private val ExtDef = DefProc("extension methods") {
- case ext: untpd.ExtMethods => Names.EmptyTermName
- }
- private val TypeDef = DefProc("type"){ case m: untpd.TypeDef => m.name }
-
- private val VarDef = Processor { case (name, code, t: untpd.ValDef) =>
- Expanded(
- //Only wrap rhs in function if it is not a function
- //Wrapping functions causes type inference errors.
- code,
- // Try to leave out all synthetics; we don't actually have proper
- // synthetic flags right now, because we're dumb-parsing it and not putting
- // it through a full compilation
- if (isPrivate(t) || t.name.decode.toString.contains("$")) Nil
- else if (t.mods.flags.is(Flags.Given)) {
- given Context = ctx
- val name0 = if (t.name.isEmpty) desugar.inventGivenOrExtensionName(t.tpt) else t.name
- Seq(pprintSignature(Name.backtickWrap(name0.decode.toString), Some("")))
- }
- else if (t.mods.flags.is(Flags.Lazy))
- Seq(pprintSignature(Name.backtickWrap(t.name.decode.toString), Some("")))
- else Seq(pprint(Name.backtickWrap(t.name.decode.toString)))
- )
- }
-
- private val PatDef = Processor { case (name, code, t: untpd.PatDef) =>
- val isLazy = t.mods.flags.is(Flags.Lazy)
- val printers =
- if (isPrivate(t)) Nil
- else
- t.pats
- .flatMap {
- case untpd.Tuple(trees) => trees
- case elem => List(elem)
- }
- .flatMap {
- case untpd.Ident(name) =>
- val decoded = name.decode.toString
- if (decoded.contains("$")) Nil
- else if (isLazy) Seq(pprintSignature(Name.backtickWrap(decoded), Some("")))
- else Seq(pprint(Name.backtickWrap(decoded)))
- case _ => Nil // can this happen?
- }
- Expanded(code, printers)
- }
-
- private val Import = Processor {
- case (name, code, tree: untpd.Import) =>
- val Array(keyword, body) = code.split(" ", 2)
- val tq = "\"\"\""
- Expanded(code, Seq(
- s"""
- _root_.ammonite
- .repl
- .ReplBridge
- .value
- .Internal
- .printImport(${Util.literalize(body)})
- """
- ))
- }
-
- private val Expr = Processor {
- //Expressions are lifted to anon function applications so they will be JITed
- case (name, code, tree) =>
- val expandedCode =
- if (markGeneratedSections)
- s"/**/val $name = /**/$code"
- else
- s"val $name = $code"
- Expanded(
- expandedCode,
- if (isPrivate(tree)) Nil else Seq(pprint(name))
- )
- }
-
- private val decls = Seq[(String, String, untpd.Tree) => Option[Expanded]](
- ObjectDef, ClassDef, TraitDef, DefDef, ExtDef, TypeDef, VarDef, PatDef, Import, Expr
- )
-
- private def complete(
- code: String,
- resultIndex: String,
- postSplit: Seq[String]
- ): Either[String, Expanded] = {
- val reParsed = postSplit.map(p => (parse(p), p))
- val errors = reParsed.collect{case (Left(e), _) => e }.flatten
- if (errors.length != 0) Left(errors.mkString(System.lineSeparator()))
- else {
- val allDecls = for {
- ((Right(trees), code), i) <- reParsed.zipWithIndex if trees.nonEmpty
- } yield {
- // Suffix the name of the result variable with the index of
- // the tree if there is more than one statement in this command
- val suffix = if (reParsed.length > 1) "_" + i else ""
- def handleTree(t: untpd.Tree) = {
- // println(s"handleTree($t)")
- val it = decls.iterator.flatMap(_.apply(code, "res" + resultIndex + suffix, t))
- if (it.hasNext)
- it.next()
- else {
- sys.error(s"Don't know how to handle ${t.getClass}: $t")
- }
- }
- trees match {
- case Seq(tree) => handleTree(tree)
-
- // This handles the multi-import case `import a.b, c.d`
- case trees if trees.forall(_.isInstanceOf[untpd.Import]) => handleTree(trees(0))
-
- // AFAIK this can only happen for pattern-matching multi-assignment,
- // which for some reason parse into a list of statements. In such a
- // scenario, aggregate all their printers, but only output the code once
- case trees =>
- val printers = for {
- tree <- trees
- if tree.isInstanceOf[untpd.ValDef]
- Expanded(_, printers) = handleTree(tree)
- printer <- printers
- } yield printer
-
- Expanded(code, printers)
- }
- }
-
- val expanded = allDecls match{
- case Seq(first, rest@_*) =>
- val allDeclsWithComments = Expanded(first.code, first.printer) +: rest
- allDeclsWithComments.reduce { (a, b) =>
- Expanded(
- // We do not need to separate the code with our own semi-colons
- // or newlines, as each expanded code snippet itself comes with
- // it's own trailing newline/semicolons as a result of the
- // initial split
- a.code + b.code,
- a.printer ++ b.printer
- )
- }
- case Nil => Expanded("", Nil)
- }
-
- Right(expanded)
- }
- }
-}
diff --git a/amm/compiler/src/main/scala-3.4.2+/ammonite/compiler/AmmonitePhase.scala b/amm/compiler/src/main/scala-3/ammonite/compiler/AmmonitePhase.scala
similarity index 100%
rename from amm/compiler/src/main/scala-3.4.2+/ammonite/compiler/AmmonitePhase.scala
rename to amm/compiler/src/main/scala-3/ammonite/compiler/AmmonitePhase.scala
diff --git a/amm/compiler/src/main/scala-3.4.2+/ammonite/compiler/Preprocessor.scala b/amm/compiler/src/main/scala-3/ammonite/compiler/Preprocessor.scala
similarity index 100%
rename from amm/compiler/src/main/scala-3.4.2+/ammonite/compiler/Preprocessor.scala
rename to amm/compiler/src/main/scala-3/ammonite/compiler/Preprocessor.scala