From 5a4fe8988c7c011554fef0c31777f74642914486 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 12 May 2020 16:48:03 +0200 Subject: [PATCH] Fix #8520: Add Reflection.Symbol.typeMembers --- .../tastyreflect/ReflectionCompilerInterface.scala | 6 ++++++ library/src/scala/tasty/Reflection.scala | 8 ++++++++ .../src/scala/tasty/reflect/CompilerInterface.scala | 6 ++++++ tests/run-macros/i8520.check | 3 +++ tests/run-macros/i8520/Macro_1.scala | 13 +++++++++++++ tests/run-macros/i8520/Test_2.scala | 9 +++++++++ 6 files changed, 45 insertions(+) create mode 100644 tests/run-macros/i8520.check create mode 100644 tests/run-macros/i8520/Macro_1.scala create mode 100644 tests/run-macros/i8520/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index c2bb1173aced..60527714850a 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1732,6 +1732,12 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case sym if isMethod(sym) && sym.name.toString == name => sym.asTerm }.toList + def Symbol_typeMembers(self: Symbol)(using ctx: Context): List[Symbol] = + self.unforcedDecls.filter(_.isType) + + def Symbol_typeMember(self: Symbol)(name: String)(using ctx: Context): Symbol = + self.unforcedDecls.find(sym => sym.name == name.toTypeName) + def Symbol_classMethods(self: Symbol)(using ctx: Context): List[Symbol] = self.typeRef.decls.iterator.collect { case sym if isMethod(sym) => sym.asTerm diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index d3f6e63719b7..b6f881f4584c 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -2219,6 +2219,14 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => def classMethods(using ctx: Context): List[Symbol] = internal.Symbol_classMethods(sym) + /** Type member directly declared in the class */ + def typeMembers(using ctx: Context): List[Symbol] = + internal.Symbol_typeMembers(sym) + + /** Type member with the given name directly declared in the class */ + def typeMember(name: String)(using ctx: Context): Symbol = + internal.Symbol_typeMember(sym)(name) + /** Get named non-private methods declared or inherited */ def method(name: String)(using ctx: Context): List[Symbol] = internal.Symbol_method(sym)(name) diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index 55ac971e4ffb..d8ae349f6594 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -1308,6 +1308,12 @@ trait CompilerInterface { /** Get all non-private methods declared or inherited */ def Symbol_methods(self: Symbol)(using ctx: Context): List[Symbol] + /** Type member directly declared in the class */ + def Symbol_typeMembers(self: Symbol)(using ctx: Context): List[Symbol] + + /** Type member with the given name directly declared in the class */ + def Symbol_typeMember(self: Symbol)(name: String)(using ctx: Context): Symbol + /** The symbols of each type parameter list and value parameter list of this * method, or Nil if this isn't a method. */ diff --git a/tests/run-macros/i8520.check b/tests/run-macros/i8520.check new file mode 100644 index 000000000000..ef34dd33b1e3 --- /dev/null +++ b/tests/run-macros/i8520.check @@ -0,0 +1,3 @@ +List((A,+)) +List((B,-)) +List((C, )) diff --git a/tests/run-macros/i8520/Macro_1.scala b/tests/run-macros/i8520/Macro_1.scala new file mode 100644 index 000000000000..7ad9e353bb35 --- /dev/null +++ b/tests/run-macros/i8520/Macro_1.scala @@ -0,0 +1,13 @@ +import scala.quoted._ + +inline def test[T[_]]: Unit = ${ testExpr[T] } + +def testExpr[T[_]: Type](using QuoteContext): Expr[Unit] = { + import qctx.tasty._ + def variance(f: Flags) = + if f.is(Flags.Covariant) then "+" + else if f.is(Flags.Contravariant) then "-" + else " " + val t = '[T].unseal.tpe.typeSymbol.typeMembers.map(x => (x.name, variance(x.flags))) + '{ println(${Expr(t.toString)}) } +} diff --git a/tests/run-macros/i8520/Test_2.scala b/tests/run-macros/i8520/Test_2.scala new file mode 100644 index 000000000000..c2448eb71651 --- /dev/null +++ b/tests/run-macros/i8520/Test_2.scala @@ -0,0 +1,9 @@ +trait X[+A] +trait Y[-B] +trait Z[C] + +@main def Test = { + test[X] + test[Y] + test[Z] +}