From 4971581667089bab06f303ff8b695d85c0547558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Thu, 26 Aug 2021 13:33:57 +0200 Subject: [PATCH] Add Symbol.isSuperAccessor to reflection API --- .../quoted/runtime/impl/QuotesImpl.scala | 1 + library/src/scala/quoted/Quotes.scala | 4 ++ .../scaladoc/tasty/SyntheticSupport.scala | 1 + .../run-tasty-inspector/isSuperAccessor.check | 1 + .../run-tasty-inspector/isSuperAccessor.scala | 39 +++++++++++++++++++ .../stdlibExperimentalDefinitions.scala | 4 +- 6 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/run-tasty-inspector/isSuperAccessor.check create mode 100644 tests/run-tasty-inspector/isSuperAccessor.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 04d8d7bc51a0..318e6f131e1b 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -2675,6 +2675,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def isAnonymousFunction: Boolean = self.denot.isAnonymousFunction def isAbstractType: Boolean = self.denot.isAbstractType def isClassConstructor: Boolean = self.denot.isClassConstructor + def isSuperAccessor = self.name.is(dotc.core.NameKinds.SuperAccessorName) def isType: Boolean = self.isType def isTerm: Boolean = self.isTerm def isPackageDef: Boolean = self.is(dotc.core.Flags.Package) diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index fa96b73551d1..3e3ffb8983d5 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -3998,6 +3998,10 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => /** Is this the constructor of a class? */ def isClassConstructor: Boolean + /** Is this the super accessor? */ + @experimental // TODO when stable, remove `dotty.tools.scaladoc.tasty.ClassLikeSupport.isSuperBridgeMethod` and use this method + def isSuperAccessor: Boolean + /** Is this the definition of a type? */ def isType: Boolean diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala index b33d5f61faac..2f85345baddc 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala @@ -10,6 +10,7 @@ object SyntheticsSupport: import reflect._ s.flags.is(Flags.Synthetic) || s.flags.is(Flags.FieldAccessor) || s.isDefaultHelperMethod + // TODO remove and use `SymbolMethods.isSuperAccessor` def isSuperBridgeMethod: Boolean = s.name.contains("$super$") def isDefaultHelperMethod: Boolean = ".*\\$default\\$\\d+$".r.matches(s.name) diff --git a/tests/run-tasty-inspector/isSuperAccessor.check b/tests/run-tasty-inspector/isSuperAccessor.check new file mode 100644 index 000000000000..4c90083e2b6b --- /dev/null +++ b/tests/run-tasty-inspector/isSuperAccessor.check @@ -0,0 +1 @@ +method SyncIterator$$super$next diff --git a/tests/run-tasty-inspector/isSuperAccessor.scala b/tests/run-tasty-inspector/isSuperAccessor.scala new file mode 100644 index 000000000000..3b950f8c79cf --- /dev/null +++ b/tests/run-tasty-inspector/isSuperAccessor.scala @@ -0,0 +1,39 @@ +import scala.quoted.* +import scala.tasty.inspector.* + +@main def Test = { + // Artefact of the current test infrastructure + // TODO improve infrastructure to avoid needing this code on each test + val classpath = dotty.tools.dotc.util.ClasspathFromClassloader(this.getClass.getClassLoader).split(java.io.File.pathSeparator).find(_.contains("runWithCompiler")).get + val allTastyFiles = dotty.tools.io.Path(classpath).walkFilter(_.extension == "tasty").map(_.toString).toList + val tastyFiles = allTastyFiles.filter(_.contains("SyncIterator")) + + TastyInspector.inspectTastyFiles(tastyFiles)(new MyInspector) +} + +class MyInspector extends Inspector: + + override def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = + import quotes.reflect.* + class Traverser extends TreeTraverser: + override def traverseTree(tree: Tree)(owner: Symbol) = + tree match + case tree: DefDef if tree.symbol.isSuperAccessor => + println(tree.symbol) + case _ => + super.traverseTree(tree)(owner) + end Traverser + + val traverser = new Traverser + tastys.foreach { tasty => + traverser.traverseTree(tasty.ast)(tasty.ast.symbol) + } + + +trait IntIterator { + def next: Int + def drop(n: Int): Unit +} +trait SyncIterator extends IntIterator { + abstract override def next: Int = super.next +} diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 111c8c0bada3..74d1124777aa 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -72,7 +72,9 @@ val experimentalDefinitionInLibrary = Set( "scala.annotation.init$.region", //// New APIs: Quotes - // Can be stabilized in 3.4.0 (unsure) or later + // Can be stabilized in 3.5.0 or later + "scala.quoted.Quotes.reflectModule.SymbolMethods.isSuperAccessor", + // Can be stabilized in 3.5.0 (unsure) or later "scala.quoted.Quotes.reflectModule.CompilationInfoModule.XmacroSettings", // Cant be stabilized yet. // Need newClass variant that can add constructor parameters.