Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 1 addition & 11 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Full per-file list with locations is in the Backlog table below (filter rows whe

## Backlog

*Auto-derived from `git grep -nE 'TODO\[scala3-port\]'` on this PR's tip. Total tags: 155.*
*Auto-derived from `git grep -nE 'TODO\[scala3-port\]'` on this PR's tip. Total tags: 144.*

| Location | Description | Effort |
|---------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|--------|
Expand All @@ -118,16 +118,6 @@ Full per-file list with locations is in the Backlog table below (filter rows whe
| `core/jvm/src/test/scala/com/avsystem/commons/macros/TypeClassDerivationTest.scala:4` | TypeClassDerivationTest — depends on TestMacros / scala-2 `def ... = macro ...` | M |
| `core/jvm/src/test/scala/com/avsystem/commons/serialization/JCodecTestBase.scala:4` | JCodecTestBase — depends on commented serialization test data / stubbed materialize | M |
| `core/jvm/src/test/scala/com/avsystem/commons/serialization/JGenCodecTest.scala:4` | JGenCodecTest — depends on commented serialization test data / stubbed materialize | M |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:129` | showAst (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:131` | showRawAst (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:133` | showSymbol (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:135` | showSymbolFullName (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:137` | showType (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:139` | showRawType (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:141` | showTypeSymbol (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:143` | showTypeSymbolFullName (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:145` | sourceCode (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/SharedExtensions.scala:147` | withSourceCode (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/annotation/AnnotationAggregate.scala:52` | reifyAggregated (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/annotation/positioned.scala:12` | here (Scala 2 macro def) | L |
| `core/src/main/scala/com/avsystem/commons/di/Components.scala:18` | component (Scala 2 macro def) | L |
Expand Down
139 changes: 117 additions & 22 deletions core/src/main/scala/com/avsystem/commons/SharedExtensions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.avsystem.commons.misc.*

import scala.annotation.nowarn
import scala.collection.{mutable, AbstractIterator, BuildFrom, Factory}
import scala.quoted.Expr

trait SharedExtensions {

Expand Down Expand Up @@ -126,28 +127,122 @@ object SharedExtensionsUtils extends SharedExtensions {
def uncheckedMatch[B](pf: PartialFunction[A, B]): B =
pf.applyOrElse(a, (obj: A) => throw new MatchError(obj))

// TODO[scala3-port]: showAst (Scala 2 macro def) (L)
def showAst: A = ???
// TODO[scala3-port]: showRawAst (Scala 2 macro def) (L)
def showRawAst: A = ???
// TODO[scala3-port]: showSymbol (Scala 2 macro def) (L)
def showSymbol: A = ???
// TODO[scala3-port]: showSymbolFullName (Scala 2 macro def) (L)
def showSymbolFullName: A = ???
// TODO[scala3-port]: showType (Scala 2 macro def) (L)
def showType: A = ???
// TODO[scala3-port]: showRawType (Scala 2 macro def) (L)
def showRawType: A = ???
// TODO[scala3-port]: showTypeSymbol (Scala 2 macro def) (L)
def showTypeSymbol: A = ???
// TODO[scala3-port]: showTypeSymbolFullName (Scala 2 macro def) (L)
def showTypeSymbolFullName: A = ???
// TODO[scala3-port]: sourceCode (Scala 2 macro def) (L)
def sourceCode: String = ???
// TODO[scala3-port]: withSourceCode (Scala 2 macro def) (L)
def withSourceCode: (A, String) = ???

def debugMacro: A = a
inline def showAst: A = ${ UniversalOps.showAstImpl[A]('a) }
inline def showSymbol: A = ${ UniversalOps.showSymbolImpl[A]('a) }
inline def showType: A = ${ UniversalOps.showTypeImpl[A]('a) }
inline def showRawType: A = ${ UniversalOps.showRawTypeImpl[A]('a) }
inline def showTypeSymbol: A = ${ UniversalOps.showTypeSymbolImpl[A]('a) }
inline def sourceCode: String = ${ UniversalOps.sourceCodeImpl[A]('a) }
inline def withSourceCode: (A, String) = ${ UniversalOps.withSourceCodeImpl[A]('a) }
}

object UniversalOps {

import scala.quoted.*

/** Detailed multi-line dump of a `quotes.reflect.Symbol`. Inspired by the `made` library. */
private def symbolInfo(using quotes: Quotes)(symbol: quotes.reflect.Symbol): String =
import quotes.reflect.*
s"""
|$symbol
|maybeOwner: ${symbol.maybeOwner}
|flags: ${symbol.flags.show}
|privateWithin: ${symbol.privateWithin.map(_.show)}
|protectedWithin: ${symbol.protectedWithin.map(_.show)}
|name: ${symbol.name}
|fullName: ${symbol.fullName}
|pos: ${symbol.pos}
|docstring: ${symbol.docstring}
|tree: ${scala.util.Try(symbol.tree.show).getOrElse("no tree")}
|annotations: ${symbol.annotations.map(_.show)}
|isDefinedInCurrentRun: ${symbol.isDefinedInCurrentRun}
|isClassDef: ${symbol.isClassDef}
|isTypeDef: ${symbol.isTypeDef}
|isValDef: ${symbol.isValDef}
|isDefDef: ${symbol.isDefDef}
|isBind: ${symbol.isBind}
|isNoSymbol: ${symbol.isNoSymbol}
|exists: ${symbol.exists}
|declaredFields: ${symbol.declaredFields}
|declaredMethods: ${symbol.declaredMethods}
|declaredTypes: ${symbol.declaredTypes}
|paramSymss: ${symbol.paramSymss}
|primaryConstructor: ${symbol.primaryConstructor}
|caseFields: ${symbol.caseFields}
|signature: ${symbol.signature}
|companionClass: ${symbol.companionClass}
|companionModule: ${symbol.companionModule}
|children: ${symbol.children}
|typeRef: ${scala.util.Try(symbol.typeRef.show).getOrElse("no typeRef")}
|termRef: ${scala.util.Try(symbol.termRef.show).getOrElse("no termRef")}
|""".stripMargin

/** Detailed multi-line dump of a `quotes.reflect.TypeRepr`. Inspired by `made`. */
private def typeReprInfo(using quotes: Quotes)(tpe: quotes.reflect.TypeRepr): String =
s"""
|type: ${tpe.show}
|raw: $tpe
|widen: ${tpe.widen.show}
|dealias: ${tpe.dealias.show}
|simplified: ${tpe.simplified.show}
|classSymbol: ${tpe.classSymbol}
|typeSymbol: ${tpe.typeSymbol}
|termSymbol: ${tpe.termSymbol}
|isSingleton: ${tpe.isSingleton}
|baseClasses: ${tpe.baseClasses}
|isFunctionType: ${tpe.isFunctionType}
|isContextFunctionType: ${tpe.isContextFunctionType}
|isDependentFunctionType: ${tpe.isDependentFunctionType}
|isTupleN: ${tpe.isTupleN}
|typeArgs: ${tpe.typeArgs}
|""".stripMargin

/** Structure + short-code dump of a `quotes.reflect.Tree`. Inspired by `made`. */
private def treeInfo(using quotes: Quotes)(tree: quotes.reflect.Tree): String =
import quotes.reflect.*
s"""
|Structure: ${Printer.TreeStructure.show(tree)}
|ShortCode: ${Printer.TreeShortCode.show(tree)}
|""".stripMargin

def showAstImpl[A: Type](a: Expr[A])(using Quotes): Expr[A] =
import quotes.reflect.*
report.info(treeInfo(a.asTerm), a)
a

def showSymbolImpl[A: Type](a: Expr[A])(using Quotes): Expr[A] =
import quotes.reflect.*
report.info(symbolInfo(a.asTerm.symbol), a)
a

def showTypeImpl[A: Type](a: Expr[A])(using Quotes): Expr[A] =
import quotes.reflect.*
report.info(typeReprInfo(TypeRepr.of[A]), a)
a

def showRawTypeImpl[A: Type](a: Expr[A])(using Quotes): Expr[A] =
import quotes.reflect.*
report.info(Printer.TypeReprStructure.show(TypeRepr.of[A].widen), a)
a

def showTypeSymbolImpl[A: Type](a: Expr[A])(using Quotes): Expr[A] =
import quotes.reflect.*
report.info(symbolInfo(TypeRepr.of[A].typeSymbol), a)
a

def sourceCodeImpl[A: Type](a: Expr[A])(using quotes: Quotes): Expr[String] =
import quotes.reflect.*
import quotes.reflect.PositionMethods // bypass package-object auto-import of `universalOps`
extension (pos: Position) def sourceCodeOption = PositionMethods.sourceCode(pos).filter(_.nonEmpty)

a.asTerm.underlyingArgument.pos.sourceCodeOption
.orElse(a.asTerm.pos.sourceCodeOption)
.orElse(Position.ofMacroExpansion.sourceCodeOption)
.getOrElse(report.errorAndAbort("source code unavailable at this position", a))
.|>(Expr.apply)

def withSourceCodeImpl[A: Type](a: Expr[A])(using Quotes): Expr[(A, String)] =
'{ ($a, ${ sourceCodeImpl[A](a) }) }
}

class LazyUniversalOps[A](private val a: () => A) extends AnyVal {
Expand Down
Loading