@@ -5,7 +5,7 @@ class methods, fields, and source code URL.
55
66from typing import Any , Dict , List
77
8- from scyjava ._jvm import jimport
8+ from scyjava ._jvm import jimport , jvm_version
99from scyjava ._types import isjava , jinstance , jclass
1010
1111
@@ -78,34 +78,49 @@ def jreflect(data, aspect: str = "all") -> List[Dict[str, Any]]:
7878 return table
7979
8080
81- def jsource (data ):
81+ def jsource (data ) -> str :
8282 """
83- Try to find the source code using SciJava's SourceFinder.
83+ Try to find the source code URL for the given Java object, class, or class name.
84+ Requires org.scijava:scijava-search on the classpath.
8485 :param data:
85- The object or class or fully qualified class name to check for source code.
86- :return: The URL of the java class
86+ Object, class, or fully qualified class name for which to discern the source code location .
87+ :return: URL of the class's source code.
8788 """
88- Types = jimport ("org.scijava.util.Types" )
89+
90+ if not isjava (data ) and isinstance (data , str ):
91+ try :
92+ data = jimport (data ) # check if data can be imported
93+ except Exception as err :
94+ raise ValueError (f"Not a Java object { err } " )
95+ jcls = data if jinstance (data , "java.lang.Class" ) else jclass (data )
96+
97+ if jcls .getClassLoader () is None :
98+ # Class is from the Java standard library.
99+ cls_path = jcls .getName ().replace ("." , "/" )
100+
101+ # Discern the Java version.
102+ java_version = jvm_version ()[0 ]
103+
104+ # Note: some classes (e.g. corba and jaxp) will not be located correctly before
105+ # Java 10, because they fall under a different subtree than `jdk`. But Java 11+
106+ # dispenses with such subtrees in favor of using only the module designations.
107+ if java_version <= 7 :
108+ return f"https://github.com/openjdk/jdk/blob/jdk7-b147/jdk/src/share/classes/{ cls_path } .java"
109+ elif java_version == 8 :
110+ return f"https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/{ cls_path } .java"
111+ else : # java_version >= 9
112+ module_name = jcls .getModule ().getName ()
113+ # if module_name is null, it's in the unnamed module
114+ if java_version == 9 :
115+ suffix = "%2B181/jdk"
116+ elif java_version == 10 :
117+ suffix = "%2B46"
118+ else :
119+ suffix = "-ga"
120+ return f"https://github.com/openjdk/jdk/blob/jdk-{ java_version } { suffix } /src/{ module_name } /share/classes/{ cls_path } .java"
121+
122+ # Ask scijava-search for the source location.
89123 SourceFinder = jimport ("org.scijava.search.SourceFinder" )
90- String = jimport ("java.lang.String" )
91- try :
92- if not isjava (data ) and isinstance (data , str ):
93- try :
94- data = jimport (data ) # check if data can be imported
95- except Exception as err :
96- raise ValueError (f"Not a Java object { err } " )
97- jcls = data if jinstance (data , "java.lang.Class" ) else jclass (data )
98- if Types .location (jcls ).toString ().startsWith (String ("jrt" )):
99- # Handles Java RunTime (jrt) exceptions.
100- raise ValueError ("Java Builtin: GitHub source code not available" )
101- url = SourceFinder .sourceLocation (jcls , None )
102- urlstring = url .toString ()
103- return urlstring
104- except jimport ("java.lang.IllegalArgumentException" ) as err :
105- return f"Illegal argument provided { err = } , { type (err )= } "
106- except ValueError as err :
107- return f"{ err } "
108- except TypeError :
109- return f"Not a Java class { str (type (data ))} "
110- except Exception as err :
111- return f"Unexpected { err = } , { type (err )= } "
124+ url = SourceFinder .sourceLocation (jcls , None )
125+ urlstring = url .toString ()
126+ return urlstring
0 commit comments