# See the License for the specific language governing permissions and
# limitations under the License.
-# Contains the java and nit type representation used to convert java to nit code
-module model
+# Model of the parsed Java classes and their corresponding Nit types
+module model is serialize
import more_collections
import opts
import poset
+import binary::serialization
import jtype_converter
end
else
# Use the prefix and the short class name
- # e.g. given the prefix Native: java.lang.String -> NativeString
+ # e.g. given the prefix Native: java.lang.String -> CString
name = prefix + id
end
end
# Short name of the class, mangled to remove `$` (e.g. `Set`)
- fun id: String do return identifier.last.replace("$", "")
+ var id: String is lazy do return identifier.last.replace("$", "")
- # Full name of this class as used in an importation (e.g. `java.lang.Set`)
- fun package_name: String do return identifier.join(".")
+ # Full name of this class as used in java code (e.g. `java.lang.Set`)
+ var java_full_name: String is lazy do return identifier.join(".").replace("$", ".")
+
+ # Full name of this class as used by jni (e.g. `android.graphics.BitmapFactory$Options`)
+ var jni_full_name: String is lazy do return identifier.join(".")
# Name of this class for the extern declaration in Nit (e.g. `java.lang.Set[]`)
- fun extern_equivalent: String do return package_name + "[]" * array_dimension
+ var extern_equivalent: String is lazy do return jni_full_name + "[]" * array_dimension
# Full name of this class with arrays and generic values (e.g. `java.lang.Set<E>[]`)
redef fun to_s do
- var id = self.package_name
+ var id = self.java_full_name
if self.is_primitive_array then
id += "[]" * array_dimension
# Comparison based on fully qualified named
redef fun ==(other) do return other isa JavaType and
- self.package_name == other.package_name and
+ self.java_full_name == other.java_full_name and
self.array_dimension == other.array_dimension
- redef fun hash do return self.package_name.hash
+ redef fun hash do return self.java_full_name.hash
end
class NitType
var identifier: String
# If this NitType was found in `lib/android`, contains the module name to import
- var mod: nullable NitModule
+ var mod: nullable NitModuleRef
# Is this type known, wrapped and available in Nit?
var is_known: Bool = true
var constructors = new Array[JavaConstructor]
# Importations from this class
- var imports = new HashSet[NitModule]
+ var imports = new HashSet[NitModuleRef]
# Interfaces implemented by this class
var implements = new HashSet[JavaType]
# Model of all the Java class analyzed in one run
class JavaModel
- # All analyzed classes
+ # Classes analyzed in this pass
var classes = new HashMap[String, JavaClass]
+ # All classes, from this pass and from other passes
+ var all_classes: HashMap[String, JavaClass] is noserialize, lazy do
+ var classes = new HashMap[String, JavaClass]
+ classes.add_all self.classes
+
+ for model_path in sys.opt_load_models.value do
+ if not model_path.file_exists then
+ print_error "Error: model file '{model_path}' does not exist"
+ continue
+ end
+
+ var file = model_path.to_path.open_ro
+ var d = new BinaryDeserializer(file)
+ var model = d.deserialize
+ file.close
+
+ if d.errors.not_empty then
+ print_error "Error: failed to deserialize model file '{model_path}' with: {d.errors.join(", ")}"
+ continue
+ end
+
+ if not model isa JavaModel then
+ print_error "Error: model file contained a '{if model == null then "null" else model.class_name}'"
+ continue
+ end
+
+ classes.add_all model.classes
+ end
+
+ return classes
+ end
+
+ # Does this model have access to the `java.lang.Object`?
+ var knows_the_object_class: Bool = all_classes.keys.has("java.lang.Object") is lazy
+
# Add a class in `classes`
fun add_class(jclass: JavaClass)
do
- var key = jclass.class_type.package_name
+ var key = jclass.class_type.java_full_name
classes[key] = jclass
end
# Unknown types, not already wrapped and not in this pass
- var unknown_types = new HashMap[JavaType, NitType]
+ var unknown_types = new HashMap[JavaType, NitType] is noserialize
# Wrapped types, or classes analyzed in this pass
- var known_types = new HashMap[JavaType, NitType]
+ var known_types = new HashMap[JavaType, NitType] is noserialize
# Get the `NitType` corresponding to the `JavaType`
#
end
# Is being wrapped in this pass?
- var key = jtype.package_name
+ var key = jtype.java_full_name
if classes.keys.has(key) then
if jtype.array_dimension <= opt_arrays.value then
var nit_type = new NitType(jtype.extern_name)
end
# Specialization hierarchy of `classes`
- var class_hierarchy = new POSet[JavaClass]
+ var class_hierarchy = new POSet[JavaClass] is noserialize
# Fill `class_hierarchy`
fun build_class_hierarchy
object_type.identifier = ["java","lang","Object"]
# Fill POSet
- for name, java_class in classes do
+ for name, java_class in all_classes do
# Skip anonymous classes
if java_class.class_type.is_anonymous then continue
# Remove unavailable super classes
for super_type in super_classes.reverse_iterator do
# Is the super class available?
- if not classes.keys.has(super_type.package_name) then super_classes.remove(super_type)
+ if not all_classes.keys.has(super_type.java_full_name) then super_classes.remove(super_type)
end
- # If the is no explicit supers, add `java.lang.Object`
- if super_classes.is_empty and java_class.class_type != object_type then
+ # If the is no explicit supers, add `java.lang.Object` (if it is known)
+ if super_classes.is_empty and java_class.class_type != object_type and
+ knows_the_object_class then
super_classes.add object_type
end
for super_type in super_classes do
# Is the super class available?
- if not classes.keys.has(super_type.package_name) then continue
+ if not all_classes.keys.has(super_type.java_full_name) then continue
- var super_class = classes[super_type.package_name]
+ var super_class = all_classes[super_type.java_full_name]
class_hierarchy.add_edge(java_class, super_class)
end
end
# Methods intro
for java_class in linearized do
- var in_hierarchy = class_hierarchy[java_class]
- var greaters = in_hierarchy.greaters
+ var greaters = java_class.in_hierarchy.greaters
for mid, signatures in java_class.methods do
for signature in signatures do
end
# A Nit module, use to import the referenced extern classes
-class NitModule
+class NitModuleRef
# Relative path to the module
var path: String
var name: String is lazy do return path.basename(".nit")
redef fun to_s do return self.name
- redef fun ==(other) do return other isa NitModule and self.path == other.path
+ redef fun ==(other) do return other isa NitModuleRef and self.path == other.path
redef fun hash do return self.path.hash
end
# * The value is the corresponding `NitType`.
var find_extern_class: DefaultMap[String, nullable NitType] is lazy do
var map = new DefaultMap[String, nullable NitType](null)
- var modules = new HashMap[String, NitModule]
+ var modules = new HashMap[String, NitModuleRef]
var lib_paths = opt_libs.value
if lib_paths == null then lib_paths = new Array[String]
var mod = modules.get_or_null(path)
if mod == null then
- mod = new NitModule(path)
+ mod = new NitModuleRef(path)
modules[path] = mod
end
# Generate the primitive array version of each class up to the given depth
var opt_arrays = new OptionInt("Depth of the primitive array for each wrapped class (default: 1)", 1, "-a")
+
+ # Generate the primitive array version of each class up to the given depth
+ var opt_load_models = new OptionArray("Saved models to search for super-classes", "-m")
end
-redef class Text
+redef abstract class Text
# Get a copy of `self` where the first letter is capitalized
fun simple_capitalized: String
do