ronmamo / reflections

Java runtime metadata analysis
Do What The F*ck You Want To Public License
4.71k stars 700 forks source link

inconsistent behavior from getSubTypesOf for Scala classes #324

Closed jimka2001 closed 2 years ago

jimka2001 commented 3 years ago

I'm trying to use the reflections library from within Scala. When I ask for the subclasses of List[Any] I don't find any. However, when I asked on a scala help group, Help with org.reflections api, someone else tried my code and correctly found the expected subclasses.

Here is the scala code I'm using

object sanityCheck {
  val refl = new org.reflections.Reflections("")

  def main(argv:Array[String]):Unit = {
    describeSubclasses(classOf[java.lang.Number])
    makeNumber()
    describeSubclasses(classOf[List[Any]])

  }
  def describeSubclasses(cl:Class[_]):Unit = {
    import java.lang.reflect.Modifier
    // getSubTypesOf does not realize that a type is a subtype of itself
    val subs:List[Class[_]] = cl :: refl.getSubTypesOf(cl).toArray.toList.collect {
      case c: Class[_] => c
    }
    println("---------")
    for{ sub <- subs
         } println( s"$sub is " + Modifier.toString(sub.getModifiers))

  }
  def makeNumber():Unit = {
    class MyNumber extends Number {
      def doubleValue():Double = 0.0
      def longValue():Long = 0
      def intValue():Int = 0
      def floatValue():Float = 0.0F
    }
    new MyNumber
  }
}

And here is the printed output I see

---------
class java.lang.Number is public abstract
class genus.sanityCheck$MyNumber$1 is public
---------
class scala.collection.immutable.List is public abstract

Another user ran my code and sees the following, correct, output.

---------
class java.lang.Number is public abstract
class genus.sanityCheck$MyNumber$1 is public
---------
class scala.collection.immutable.List is public abstract
class scala.collection.immutable.$colon$colon is public final
class scala.collection.immutable.Nil$ is public final

I am using version 0.9.12 of the reflections library.

jimka2001 commented 3 years ago

I've done some additional experimentation. Here are several pieces of information I hope the developers find useful useful.

Scanner SubTypesScanner was not configured
org.reflections.ReflectionsException: Scanner SubTypesScanner was not configured
    at org.reflections.Store.get(Store.java:39)
    at org.reflections.Store.get(Store.java:61)
    at org.reflections.Store.get(Store.java:46)
    at org.reflections.Store.getAll(Store.java:93)
    at org.reflections.Reflections.getSubTypesOf(Reflections.java:404)
ronmamo commented 2 years ago

thanks @jimka2001

instantiating with "" is discouraged and might result in different urls resolved from the classpath. using ConfigurationBuilder explicitly is preferred.

scanner was not configured exception - this is known issue on 0.9.12, a simple workaround is to check if the store contains scanned values for the scanner before query. next version fixes this.

also matrix testing are planned to be added, if you want to contribute that'd be great

jimka2001 commented 2 years ago

Sorry I don't know anything about matrix testing. is that something I can do from Scala? A quick google search didn't reveal anything pertinent.

jimka2001 commented 2 years ago

@ronmamo, can you comment a bit more about what I need to do as a Scala programmer. I tried what you recommended (at least as best I can understand what you recommended).

import org.reflections.util.ConfigurationBuilder

val reflect = new org.reflections.Reflections(new ConfigurationBuilder)

In this case I find that java.lang.Number is the only subclass of java.lang.Number.

However, when I use the following:

import org.reflections.util.ConfigurationBuilder

val reflect = new org.reflections.Reflections()

I see the following subclasses of java.lang.Number

--------- subclasses of class java.lang.Number
   superclass is class java.lang.Object
0: class java.lang.Number is public abstract
1: class java.lang.Float is public final
2: class scala.math.ScalaNumber is public abstract
3: class java.lang.Double is public final
4: class java.util.concurrent.atomic.Striped64 is abstract
5: class java.lang.Integer is public final
6: class java.math.BigDecimal is public
7: class java.util.concurrent.atomic.AtomicLong is public
8: class genus.sanityCheck$MyNumber$1 is public
9: class java.util.concurrent.atomic.AtomicInteger is public
10: class java.lang.Long is public final
11: class java.lang.Short is public final
12: class java.math.BigInteger is public
13: class java.lang.Byte is public final
14: class spire.math.SafeLong is public abstract
15: class spire.math.FloatNumber is public
16: class spire.math.Rational is public abstract
17: class spire.math.Real$Exact is public static
18: class spire.math.Jet is public
19: class spire.math.DecimalNumber is public
20: class scala.math.BigInt is public final
21: class spire.math.RationalNumber is public
22: class spire.math.IntNumber is public
23: class spire.math.Real$Inexact is public static
24: class spire.math.Natural is public abstract
25: class spire.math.Complex is public
26: class spire.math.Algebraic is public final
27: class spire.math.Quaternion is public
28: class scala.math.BigDecimal is public final
29: class java.util.concurrent.atomic.LongAdder is public
30: class java.util.concurrent.atomic.LongAccumulator is public
31: class java.util.concurrent.atomic.DoubleAdder is public
32: class java.util.concurrent.atomic.DoubleAccumulator is public
33: class spire.math.SafeLongBigInteger is public final
34: class spire.math.SafeLongLong is public final
35: class spire.math.Rational$BigRational is public static final
36: class spire.math.Rational$LongRational is public static final
37: class spire.math.Jet$mcD$sp is public final
38: class spire.math.Jet$mcF$sp is public final
39: class spire.math.Natural$Digit is public static
40: class spire.math.Natural$End is public static
41: class spire.math.Complex$mcD$sp is public final
42: class spire.math.Complex$mcF$sp is public final
43: class spire.math.Quaternion$mcF$sp is public final
44: class spire.math.Quaternion$mcD$sp is public final

BTW I am using version 0.10.2 of the reflections library

potatoxf commented 2 years ago

这是来自QQ邮箱的自动回复邮件。   您好,我已经收到您的邮件

mitkurale commented 1 week ago

@ronmamo I am getting the same error and we are using reflections version '0.9.11'. What is the next good version which fixes this issue? Caused by: org.reflections.ReflectionsException: Scanner SubTypesScanner was not configured at org.reflections.Store.get(Store.java:39) at org.reflections.Store.getAllIncluding(Store.java:75)