Skip to content

Update reflect Symbol declarations API #10645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ object FieldsImpl:
def fieldsImpl[V: Type, T: Type](from: Expr[V])(using Quotes): Expr[Seq[T]] =
import quotes.reflect._
val retType = TypeTree.of[T].tpe
def isProjectField(s: Symbol) =
def isProjectField(s: Symbol) =
s.isValDef && s.tree.asInstanceOf[ValDef].tpt.tpe <:< retType
val projectsTree = Term.of(from)
val symbols = TypeTree.of[V].symbol.members.filter(isProjectField)
val symbols = TypeTree.of[V].symbol.memberMethods.filter(isProjectField)
val selects = symbols.map(Select(projectsTree, _).asExprOf[T])
'{ println(${Expr(retType.show)}); ${Varargs(selects)} }
36 changes: 23 additions & 13 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2344,35 +2344,45 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
val sym = self.unforcedDecls.find(sym => sym.name == name.toTermName)
if (isField(sym)) sym else dotc.core.Symbols.NoSymbol

def classMethod(name: String): List[Symbol] =
def declaredMethod(name: String): List[Symbol] =
self.typeRef.decls.iterator.collect {
case sym if isMethod(sym) && sym.name.toString == name => sym.asTerm
}.toList

def classMethods: List[Symbol] =
def declaredMethods: List[Symbol] =
self.typeRef.decls.iterator.collect {
case sym if isMethod(sym) => sym.asTerm
}.toList

def members: List[Symbol] =
self.typeRef.info.decls.toList

def typeMembers: List[Symbol] =
self.unforcedDecls.filter(_.isType)

def typeMember(name: String): Symbol =
self.unforcedDecls.find(sym => sym.name == name.toTypeName)

def method(name: String): List[Symbol] =
def memberMethod(name: String): List[Symbol] =
appliedTypeRef(self).allMembers.iterator.map(_.symbol).collect {
case sym if isMethod(sym) && sym.name.toString == name => sym.asTerm
}.toList

def methods: List[Symbol] =
def memberMethods: List[Symbol] =
appliedTypeRef(self).allMembers.iterator.map(_.symbol).collect {
case sym if isMethod(sym) => sym.asTerm
}.toList

def declaredType(name: String): List[Symbol] =
self.typeRef.decls.iterator.collect {
case sym if sym.isType && sym.name.toString == name => sym.asType
}.toList

def declaredTypes: List[Symbol] =
self.typeRef.decls.iterator.collect {
case sym if sym.isType => sym.asType
}.toList

def memberType(name: String): Symbol =
self.unforcedDecls.find(sym => sym.name == name.toTypeName)

def memberTypes: List[Symbol] =
self.unforcedDecls.filter(_.isType)

def declarations: List[Symbol] =
self.typeRef.info.decls.toList

def paramSymss: List[List[Symbol]] = self.denot.paramSymss
def primaryConstructor: Symbol = self.denot.primaryConstructor
def allOverriddenSymbols: Iterator[Symbol] = self.denot.allOverriddenSymbols
Expand Down
30 changes: 18 additions & 12 deletions library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3155,25 +3155,31 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
def field(name: String): Symbol

/** Get non-private named methods defined directly inside the class */
def classMethod(name: String): List[Symbol]
def declaredMethod(name: String): List[Symbol]

/** Get all non-private methods defined directly inside the class, exluding constructors */
def classMethods: List[Symbol]
def declaredMethods: List[Symbol]

/** Type member directly declared in the class */
def typeMembers: List[Symbol]
/** Get named non-private methods declared or inherited */
def memberMethod(name: String): List[Symbol]

/** Type member with the given name directly declared in the class */
def typeMember(name: String): Symbol
/** Get all non-private methods declared or inherited */
def memberMethods: List[Symbol]

/** All members directly declared in the class */
def members: List[Symbol]
/** Get non-private named methods defined directly inside the class */
def declaredType(name: String): List[Symbol]

/** Get named non-private methods declared or inherited */
def method(name: String): List[Symbol]
/** Get all non-private methods defined directly inside the class, exluding constructors */
def declaredTypes: List[Symbol]

/** Get all non-private methods declared or inherited */
def methods: List[Symbol]
/** Type member with the given name directly declared in the class */
def memberType(name: String): Symbol

/** Type member directly declared in the class */
def memberTypes: List[Symbol]

/** All members directly declared in the class */
def declarations: List[Symbol]

/** The symbols of each type parameter list and value parameter list of this
* method, or Nil if this isn't a method.
Expand Down
4 changes: 2 additions & 2 deletions scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ trait ClassLikeSupport:
}
// TODO check given methods?
case dd: DefDef if !dd.symbol.isHiddenByVisibility && dd.symbol.isGiven =>
Some(dd.symbol.owner.typeMember(dd.name))
Some(dd.symbol.owner.memberType(dd.name))
.filterNot(_.exists)
.map { _ =>
parseMethod(dd.symbol, kind = Kind.Given(getGivenInstance(dd).map(_.asSignature), None))
Expand Down Expand Up @@ -156,7 +156,7 @@ trait ClassLikeSupport:
case vd: ValDef if !isSyntheticField(vd.symbol) && (!vd.symbol.flags.is(Flags.Case) || !vd.symbol.flags.is(Flags.Enum)) =>
Some(parseValDef(vd))

case c: ClassDef if c.symbol.owner.method(c.name).exists(_.flags.is(Flags.Given)) =>
case c: ClassDef if c.symbol.owner.memberMethod(c.name).exists(_.flags.is(Flags.Given)) =>
Some(parseGivenClasslike(c))

case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven =>
Expand Down
2 changes: 1 addition & 1 deletion scala3doc/src/dotty/dokka/tasty/SymOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class SymOps[Q <: Quotes](val q: Q):
else
val pointsTo =
if (!sym.isTypeDef) PointingToDeclaration.INSTANCE
else PointingToGenericParameters(sym.owner.typeMembers.indexOf(sym))
else PointingToGenericParameters(sym.owner.memberTypes.indexOf(sym))

val method =
if (sym.isDefDef) Some(sym)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import dotty.dokka.tasty.TastyParser
class CommentExpanderTests {
def check(using quoted.Quotes)(): Unit =
assertCommentEquals(
qr.Symbol.requiredClass("tests.B").method("otherMethod").head,
qr.Symbol.requiredClass("tests.B").memberMethod("otherMethod").head,
"/** This is my foo: Bar, actually. */",
)
assertCommentEquals(
qr.Symbol.requiredClass("tests.C"),
"/** This is foo: Foo expanded. */",
)
assertCommentEquals(
qr.Symbol.requiredModule("tests.O").method("method").head,
qr.Symbol.requiredModule("tests.O").memberMethod("method").head,
"/** This is foo: O's foo. */",
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ class LookupTestCases[Q <: Quotes](val q: Quotes) {
if s.flags.is(q.reflect.Flags.Module) then s.moduleClass else s
Sym(hackResolveModule(symbol.field(name)))
def fun(name: String) =
val List(sym) = symbol.method(name)
val List(sym) = symbol.memberMethod(name)
Sym(sym)
def tpe(name: String) = Sym(symbol.typeMember(name))
def tpe(name: String) = Sym(symbol.memberType(name))
}

def cls(fqn: String) = Sym(q.reflect.Symbol.classSymbol(fqn))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Interpreter[Q <: Quotes & Singleton](using q0: Q) extends TreeInterpreter[
}

// println(method)
val symbol = sym.methods.find(_.name == method.getName).get
val symbol = sym.memberMethods.find(_.name == method.getName).get

if (symbol.isDefinedInCurrentRun) {
val argsList = if (args == null) Nil else args.toList
Expand Down
8 changes: 4 additions & 4 deletions tests/run-macros/gestalt-type-toolbox-reflect/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,25 @@ object TypeToolbox {
inline def methodIn[T](inline mem: String): Seq[String] = ${methodInImpl[T]('mem)}
private def methodInImpl[T: Type](mem: Expr[String])(using Quotes) : Expr[Seq[String]] = {
import quotes.reflect._
Expr(TypeTree.of[T].symbol.classMethod(mem.valueOrError).map(_.name))
Expr(TypeTree.of[T].symbol.declaredMethod(mem.valueOrError).map(_.name))
}

inline def methodsIn[T]: Seq[String] = ${methodsInImpl[T]}
private def methodsInImpl[T: Type](using Quotes) : Expr[Seq[String]] = {
import quotes.reflect._
Expr(TypeTree.of[T].symbol.classMethods.map(_.name))
Expr(TypeTree.of[T].symbol.declaredMethods.map(_.name))
}

inline def method[T](inline mem: String): Seq[String] = ${methodImpl[T]('mem)}
private def methodImpl[T: Type](mem: Expr[String])(using Quotes) : Expr[Seq[String]] = {
import quotes.reflect._
Expr(TypeTree.of[T].symbol.method(mem.valueOrError).map(_.name))
Expr(TypeTree.of[T].symbol.memberMethod(mem.valueOrError).map(_.name))
}

inline def methods[T]: Seq[String] = ${methodsImpl[T]}
private def methodsImpl[T: Type](using Quotes) : Expr[Seq[String]] = {
import quotes.reflect._
Expr(TypeTree.of[T].symbol.methods.map(_.name))
Expr(TypeTree.of[T].symbol.memberMethods.map(_.name))
}

inline def typeTag[T](x: T): String = ${typeTagImpl[T]}
Expand Down
8 changes: 4 additions & 4 deletions tests/run-macros/i6518/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ object Macros {
private def testImpl(using Quotes) : Expr[String] = {
import quotes.reflect._
val classSym = TypeRepr.of[Function1].classSymbol.get
classSym.classMethod("apply")
classSym.classMethods
classSym.method("apply")
Expr(classSym.methods.map(_.name).sorted.mkString("\n"))
classSym.declaredMethod("apply")
classSym.declaredMethods
classSym.memberMethod("apply")
Expr(classSym.memberMethods.map(_.name).sorted.mkString("\n"))
}

}
2 changes: 1 addition & 1 deletion tests/run-macros/i8520/Macro_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ def testExpr[T[_]: Type](using Quotes): Expr[Unit] = {
if f.is(Flags.Covariant) then "+"
else if f.is(Flags.Contravariant) then "-"
else " "
val t = TypeRepr.of[T].typeSymbol.typeMembers.map(x => (x.name, variance(x.flags)))
val t = TypeRepr.of[T].typeSymbol.memberTypes.map(x => (x.name, variance(x.flags)))
'{ println(${Expr(t.toString)}) }
}
2 changes: 1 addition & 1 deletion tests/run-macros/inferred-repeated-result/test_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object Macros {
val tree = Term.of(expr)

val methods =
tree.tpe.classSymbol.get.classMethods.map { m =>
tree.tpe.classSymbol.get.declaredMethods.map { m =>
val name = m.show
m.tree match
case ddef: DefDef =>
Expand Down