default:
mkdir -p bin
make -C ../nitcc
- cp ../nitcc/src/nitcc bin/
- ./bin/nitcc ./grammar/javap.sablecc
- ../../bin/nitg ./src/javap_visitor.nit -o ./bin/jwrapper
+ ../nitcc/src/nitcc ./grammar/javap.sablecc
+ ../../bin/nitg ./src/jwrapper.nit -o ./bin/jwrapper
mv *.nit ./src/
mkdir -p gen
mv javap* ./gen/
class CodeGenerator
+ var with_attributes: Bool
+ var comment_unknown_types: Bool
var file_out: OFStream
var java_class: JavaClass
+ var nb_params: Int
+ var module_name: String
fun code_warehouse: CodeWarehouse do return once new CodeWarehouse
- init (file_name: String, jclass: JavaClass)
+ init (file_name: String, jclass: JavaClass, with_attributes, comment: Bool)
do
file_out = new OFStream.open(file_name)
+ module_name = file_name.substring(0, file_name.search(".nit").from)
self.java_class = jclass
+ self.with_attributes = with_attributes
+ self.comment_unknown_types = comment
end
fun generate
do
var jclass = self.java_class
- file_out.write("import mnit_android\n")
- gen_class_header(jclass.name)
+ var class_content = new Array[String]
+ class_content.add(gen_class_header(jclass.class_type))
- # Attributes generation
- for id, jtype in jclass.attributes do gen_attribute(id, jtype)
+ if with_attributes then
+ for id, jtype in jclass.attributes do class_content.add(gen_attribute(id, jtype))
+ end
for id, methods_info in jclass.methods do
for method_info in methods_info do
var nid = id
if methods_info.length > 1 then nid += "{methods_info.index_of(method_info)}"
- gen_method(id, nid, method_info.return_type, method_info.params)
+ class_content.add gen_method(id, nid, method_info.return_type, method_info.params)
end
end
+ class_content.add("\nend\n")
+
+ var wrappers = new Array[String]
+ for jtype in jclass.unknown_types do
+ if jtype == jclass.class_type then continue
+ wrappers.add("\n")
+ wrappers.add(gen_unknown_class_header(jtype))
+ end
+
+ var imports = new Array[String]
+ imports.add("import mnit_android\n")
+ for import_ in jclass.imports do
+ imports.add("import android::{import_}\n")
+ end
+
+ file_out.write("module {module_name}\n")
+ file_out.write(imports.join(""))
+ file_out.write("\n")
+ file_out.write(class_content.join(""))
+ file_out.write(wrappers.join(""))
+ end
- file_out.write("\nend")
+ fun gen_class_header(jtype: JavaType): String
+ do
+ var temp = new Array[String]
+ temp.add("extern class Native{jtype.id} in \"Java\" `\{ {jtype} `\}\n")
+ temp.add("\tsuper JavaObject\n\tredef type SELF: Native{jtype.id}\n\n")
+
+ return temp.join("")
end
- fun gen_class_header(full_class_name: Array[String])
+ fun gen_unknown_class_header(jtype: JavaType): String
do
- file_out.write("extern class Native{full_class_name.last} in \"Java\" `\{ {full_class_name.join(".")} `\}\n")
- file_out.write("\tsuper JavaObject\n\tredef type SELF: Native{full_class_name.last}\n\n")
+ var nit_type: NitType
+ if jtype.extern_name.has_generic_params then
+ nit_type = jtype.extern_name.generic_params.first
+ else
+ nit_type = jtype.extern_name
+ end
+
+ var temp = new Array[String]
+ temp.add("extern class {nit_type} in \"Java\" `\{ {jtype.to_package_name} `\}\n")
+ temp.add("\tsuper JavaObject\n\tredef type SELF: {nit_type}\n\nend\n")
+
+ return temp.join("")
end
- fun gen_attribute(jid: String, jtype: JavaType)
+ fun gen_attribute(jid: String, jtype: JavaType): String
do
- file_out.write("\tvar {jid.to_snake_case}: {jtype.to_nit_type}\n")
+ return "\tvar {jid.to_snake_case}: {jtype.to_nit_type}\n"
end
- fun gen_method(jmethod_id: String, nmethod_id: String, jreturn_type: JavaType, jparam_list: Array[JavaType])
+ fun gen_method(jmethod_id: String, nmethod_id: String, jreturn_type: JavaType, jparam_list: Array[JavaType]): String
do
var java_params = ""
var nit_params = ""
for i in [0..jparam_list.length[ do
var jparam = jparam_list[i]
var nit_type = jparam.to_nit_type
+
+ if not nit_type.is_complete then
+ if jparam.is_wrapped then
+ java_class.imports.add nit_type.mod.as(not null)
+ else
+ if comment_unknown_types then
+ comment = "#"
+ else
+ nit_type = jparam.extern_name
+ java_class.unknown_types.add(jparam)
+ end
+ end
+ end
+
var cast = ""
if not jparam.is_collection then cast = jparam.param_cast
end
nit_id_no += 1
- # Comment if one type is unknown
- if not nit_type.is_complete then comment = "#"
end
# Method identifier
if not jreturn_type.is_void then
return_type = jreturn_type.to_nit_type
- if not return_type.is_complete then comment = "#"
+
+ if not return_type.is_complete then
+ if jreturn_type.is_wrapped then
+ java_class.imports.add return_type.mod.as(not null)
+ else
+ if comment_unknown_types then
+ comment = "#"
+ else
+ return_type = jreturn_type.extern_name
+ java_class.unknown_types.add(jreturn_type)
+ end
+ end
+ end
+
nit_signature.add ": {return_type} "
end
- file_out.write(comment + nit_signature.join(""))
-
var param_to_copy = param_to_copy(jparam_list, nit_types)
- # Copy one parameter, the return value, one parameter and the return value or nothing
- if return_type != null then
- if return_type.is_complete and jreturn_type.is_collection then
+ var temp = new Array[String]
+
+ if nb_params > 1 then
+ comment = "#"
+ temp.add("\t# NOT SUPPORTED: more than one parameter to copy\n")
+ temp.add("\t# Has to be implemented manually\n")
+ end
+
+ temp.add(comment + nit_signature.join(""))
+
+ # FIXME : This huge `if` block is only necessary to copy primitive arrays as long as there's no better way to do it
+ if comment == "#" then
+ temp.add(" in \"Java\" `\{\n{comment}\t\trecv.{jmethod_id}({java_params}); \n{comment}\t`\}\n")
+ # Methods with return type
+ else if return_type != null then
+ if jreturn_type.is_primitive_array then
+ # Copy one parameter and the return value
if param_to_copy != null then
var rtype_couple = new Couple[JavaType, NitType](jreturn_type, return_type)
- file_out.write(code_warehouse.param_return_copy(rtype_couple, param_to_copy, jmethod_id, java_params))
+ temp.add(code_warehouse.param_return_copy(rtype_couple, param_to_copy, jmethod_id, java_params))
+ # Copy the return type
else
- file_out.write(code_warehouse.return_type_copy(jreturn_type, return_type, jmethod_id, java_params))
+ temp.add(code_warehouse.return_type_copy(jreturn_type, return_type, jmethod_id, java_params))
end
+ # Copy the parameter
else if param_to_copy != null then
- file_out.write(code_warehouse.param_type_copy(param_to_copy.first, param_to_copy.second, jmethod_id, java_params, true))
+ temp.add(code_warehouse.param_type_copy(param_to_copy.first, param_to_copy.second, jmethod_id, java_params, true))
+ # No copy
else
- file_out.write(" in \"Java\" `\{\n\t\t{comment}return {jreturn_type.return_cast} recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
+ temp.add(" in \"Java\" `\{\n{comment}\t\treturn {jreturn_type.return_cast} recv.{jmethod_id}({java_params}); \n{comment}\t`\}\n")
end
+ # Methods without return type
else if jreturn_type.is_void then
+ # Copy one parameter
if param_to_copy != null then
- file_out.write(code_warehouse.param_type_copy(param_to_copy.first, param_to_copy.second, jmethod_id, java_params, false))
+ temp.add(code_warehouse.param_type_copy(param_to_copy.first, param_to_copy.second, jmethod_id, java_params, false))
+ # No copy
else
- file_out.write(" in \"Java\" `\{\n\t\t{comment}recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
+ temp.add(" in \"Java\" `\{\n{comment}\t\trecv.{jmethod_id}({java_params}); \n{comment}\t`\}\n")
end
+ # No copy
else
- file_out.write(" in \"Java\" `\{\n\t\t{comment}recv.{jmethod_id}({java_params}); \n\t{comment}`\}\n")
+ temp.add(" in \"Java\" `\{\n{comment}\t\trecv.{jmethod_id}({java_params}); \n{comment}\t`\}\n")
end
+
+ return temp.join("")
end
- # Only one collection type parameter can be copied
+ # Only one primitive array parameter can be copied
# If there's none or more than one then `null` is returned
fun param_to_copy(jtypes: Array[JavaType], ntypes: Array[NitType]): nullable Couple[JavaType, NitType]
do
var counter = 0
var couple = null
for i in [0..jtypes.length[ do
- if jtypes[i].is_collection and ntypes[i].is_complete then
+ if jtypes[i].is_primitive_array then
counter += 1
- if counter > 1 then return null
couple = new Couple[JavaType, NitType](jtypes[i], ntypes[i])
end
end
+ nb_params = counter
+
+ if counter > 1 then return null
return couple
end
end
return {{{narray_id}}};
`}
- """
+"""
end
# Collection as parameter
{{{return_str}}}recv.{{{jmethod_id}}}({{{params_id}}});
`}
- """
+"""
end
# One collection parameter and the return type will be copied
return {{{narray_id2}}};
`}
- """
+"""
end
private fun create_array_instance(java_type: JavaType, nit_type: NitType, jarray_id: String): String
var instanciation = ""
if java_type.is_primitive_array then
- instanciation = "{jtype} {jarray_id} = new {java_type.full_id}[Array_of_{nit_type.generic_params[0]}_length({nit_type.arg_id})];"
+ instanciation = "{jtype} {jarray_id} = new {java_type.full_id}[(int)Array_of_{nit_type.generic_params[0]}_length({nit_type.arg_id})];"
else
instanciation = "{jtype} {jarray_id} = new {jtype}();"
end
if not is_param then
if nit_type.is_map then
- imports = """import {{{ntype}}}, {{{ntype}}}.[]="""
+ imports = """ import {{{ntype}}}, {{{ntype}}}.[]="""
else
- imports = """import {{{ntype}}}, {{{ntype}}}.add"""
+ imports = """ import {{{ntype}}}, {{{ntype}}}.add"""
end
else if nit_type.id == "Array" then
- imports = """import {{{ntype}}}.length, {{{ntype}}}.[]"""
+ imports = """ import {{{ntype}}}, {{{ntype}}}.length, {{{ntype}}}.[]"""
else if nit_type.is_map then
- imports = """import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item, Iterator[{{{gen_type}}}].key"""
+ imports = """ import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item, Iterator[{{{gen_type}}}].key"""
else
- imports = """import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item"""
+ imports = """ import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item"""
end
return imports
loop_header = "for(int i=0; i < {jarray_id}.length; ++i)"
loop_body = """\t\t\t{{{jarray_id}}}[i] = {{{java_type.param_cast}}}Array_of_{{{gen_type}}}__index({{{nit_type.arg_id}}}, i);"""
else if nit_type.id == "Array" then
- loop_header = """int length = Array_of_{{{gen_type}}}_length({{{nit_type.arg_id}}});\n\t\tfor(int i=0; i < length; ++i)"""
+ loop_header = """int length = Array_of_{{{gen_type}}}_length((int){{{nit_type.arg_id}}});\n\t\tfor(int i=0; i < length; ++i)"""
loop_body = """\t\t\t{{{jarray_id}}}.add({{{java_type.param_cast}}}Array_of_{{{gen_type}}}__index({{{narray_id}}}, i));"""
else
loop_header = """int itr = {{{nit_type.id}}}_of_{{{gen_type}}}_iterator({{{nit_type.arg_id}}});\n\t\twhile(Iterator_of_{{{gen_type}}}_is_ok(itr)) {"""
var key_cast = java_type.to_cast(java_type.generic_params[0].id, false)
var value_cast = java_type.to_cast(java_type.generic_params[1].id, false)
loop_header = """for (java.util.Map.Entry<{{{java_type.generic_params[0]}}}, {{{java_type.generic_params[1]}}}> e: {{{jarray_id}}})"""
- loop_body = """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_{{{nit_type.generic_params[1]}}}__index_assign({{{narray_id}}}, {{{key_cast}}}e.getKey(), {{{value_cast}}}e.getValue()); """
+ loop_body = """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_{{{nit_type.generic_params[1]}}}__index_assign({{{narray_id}}}, {{{key_cast}}}e.getKey(), {{{value_cast}}}e.getValue());"""
else if java_type.is_iterable then
loop_header = """for ({{{java_type.generic_params[0]}}} e: {{{jarray_id}}})"""
loop_body = """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_add({{{narray_id}}}, {{{java_type.return_cast}}}e);"""
import javap_test_parser
import code_generator
+import jtype_converter
intrude import types
class JavaVisitor
super Visitor
+ var converter: JavaTypeConverter
+
var java_class = new JavaClass
var declaration_type: nullable String = null
var declaration_element: nullable String = null
- var full_class_name = new Array[String]
+ var class_type: JavaType
var variable_id = ""
- var variable_type = new JavaType
+ var variable_type: JavaType
var is_generic_param = false
+ var is_generic_id = false
+ var generic_id = ""
var gen_params_index = 0
+ # Used to resolve generic return types (T -> foo.faz.Bar)
+ var generic_map = new HashMap[String, Array[String]]
+
var is_primitive_array = false
var method_id = ""
- var method_return_type = new JavaType
+ var method_return_type: JavaType
var method_params = new Array[JavaType]
var param_index = 0
redef fun visit(n) do n.accept_visitor(self)
+
+ init(converter: JavaTypeConverter)
+ do
+ self.converter = converter
+ self.class_type = new JavaType(self.converter)
+ self.method_return_type = new JavaType(self.converter)
+ self.variable_type = new JavaType(self.converter)
+ super
+ end
end
redef class Node
if v.declaration_type == "class_header" then
if v.declaration_element == "id" then
- v.full_class_name.add(self.text)
+ v.class_type.identifier.add(self.text)
end
else if v.declaration_type == "variable" then
else
v.method_params[v.param_index].identifier.add(self.text)
end
+
+ # Creates a map to resolve generic return types
+ # Exemple : public **<T extends android/os/Bundle>** T foo();
+ else if v.is_generic_param then
+ if v.is_generic_id then
+ v.generic_id = self.text
+ v.generic_map[self.text] = new Array[String]
+
+ if not v.method_return_type.has_unresolved_types then v.method_return_type.has_unresolved_types = true
+ else
+ v.generic_map[v.generic_id].add(self.text)
+ end
end
end
v.declaration_type = null
v.declaration_element = null
- v.java_class.name = v.full_class_name
+ v.java_class.class_type = v.class_type
end
end
super
v.declaration_type = null
+ if v.method_return_type.has_unresolved_types then v.method_return_type.resolve_types(v.generic_map)
v.java_class.add_method(v.method_id, v.method_return_type, v.method_params)
v.method_params.clear
v.method_id = ""
- v.method_return_type = new JavaType
+ v.method_return_type = new JavaType(v.converter)
end
end
v.java_class.attributes[v.variable_id] = v.variable_type
v.variable_id = ""
- v.variable_type = new JavaType
+ v.variable_type = new JavaType(v.converter)
end
end
end
if v.declaration_type == "method" and v.declaration_element == null then
- v.declaration_element = "return_type"
+ # Makes sure it is not the generic return type definition
+ if not (v.method_return_type.identifier.is_empty and v.is_generic_param) then
+ v.declaration_element = "return_type"
+ end
end
super
# Ignore the weird generic return type declaration
if v.declaration_type == "method" then
if v.declaration_element == null then
- v.declaration_element = "ignore"
+ v.is_generic_param = true
else
v.is_generic_param = true
v.gen_params_index = 0
end
end
+redef class Ngeneric_identifier
+ redef fun accept_visitor(v)
+ do
+ if v.declaration_type == "method" then
+ if v.declaration_element == null then
+ v.is_generic_id = true
+ end
+ end
+
+ super
+
+ v.is_generic_id = false
+
+ end
+end
+
redef class Nparameter_list
redef fun accept_visitor(v)
do
if v.declaration_type == "method" then
if v.declaration_element == "parameter_list" then
if v.is_generic_param then
- v.method_params[v.param_index].generic_params.add(new JavaType)
+ v.method_params[v.param_index].generic_params.add(new JavaType(v.converter))
super
v.gen_params_index += 1
else
- v.method_params.add(new JavaType)
+ v.method_params.add(new JavaType(v.converter))
super
end
else if v.declaration_element == "return_type" and v.is_generic_param then
- v.method_return_type.generic_params.add(new JavaType)
+ v.method_return_type.generic_params.add(new JavaType(v.converter))
super
v.gen_params_index += 1
+
+ # For generic return type definition
+ else if v.declaration_element == null then
+ super
end
else if v.declaration_type == "variable" then
if v.declaration_element == "type" and v.is_generic_param then
- v.variable_type.generic_params.add(new JavaType)
+ v.variable_type.generic_params.add(new JavaType(v.converter))
super
end
end
end
-
-var p = new TestParser_javap
-var tree = p.main
-
-var visitor = new JavaVisitor
-visitor.enter_visit(tree)
-
-var generator = new CodeGenerator("bundle.nit", visitor.java_class)
-generator.generate
type_map["boolean"] = "Bool"
type_map["Boolean"] = "Bool"
type_map["Object"] = "JavaObject"
- type_map["Bundle"] = "NativeBundle"
type_map["String"] = "JavaString"
type_map["CharSequence"] = "JavaString"
+
+ # Cast if the type is given as a parameter
+ param_cast_map["byte"] = "(byte)"
+ param_cast_map["Byte"] = "(Byte)"
+ param_cast_map["short"] = "(short)"
+ param_cast_map["Short"] = "(short)"
+ param_cast_map["float"] = "(float)"
+ param_cast_map["Float"] = "(float)"
+ param_cast_map["int"] = "(int)"
+ param_cast_map["Integer"] = "(int)"
+
+ # Cast if the type is given as a return value
+ return_cast_map["CharSequence"] = "(String)"
+ end
+
+ init with_collections
+ do
+ self.init
# Collections
type_map["List"] = "Array"
type_map["ArrayList"] = "Array"
type_map["TreeMap"] = "RBTreeMap"
type_map["Hashtable"] = "HashMap"
type_map["LinkedHashMap"] = "HashMap"
-
- # Cast if the type is given as a parameter
- param_cast_map["byte"] = "(byte)"
- param_cast_map["Byte"] = "(Byte)"
- param_cast_map["short"] = "(short)"
- param_cast_map["Short"] = "(short)"
- param_cast_map["float"] = "(float)"
- param_cast_map["Float"] = "(float)"
- # FIXME: Uncomment as soon as Nit `Int` will be equivalent to Java `long`
- # param_cast_map["int"] = "int"
- # param_cast_map["Integer"] = "int"
-
- # Cast if the type is given as a return value
- return_cast_map["CharSequence"] = "(String)"
- # FIXME: Erase as soon as the Nit `Int` type will become a Java `long`
- return_cast_map["long"] = "(int)"
end
fun to_nit_type(java_type: String): nullable String
import jtype_converter
class JavaType
- private var converter = new JavaTypeConverter
- var identifier: Array[String] = new Array[String]
+ private var converter: JavaTypeConverter
+ var identifier = new Array[String]
var generic_params: nullable Array[JavaType] = null
var is_void = false
+
+ # Has some generic type to be resolved (T extends foo => T is resolved to foo)
+ var has_unresolved_types = false
+
+ # Dimension of primitive array: `int[][]` is 2d
var array_dimension = 0
- fun collections_list: Array[String] is cached do return ["List", "ArrayList", "LinkedList", "Vector", "Set", "SortedSet", "HashSet", "TreeSet", "LinkedHashSet", "Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
- fun iterable: Array[String] is cached do return ["ArrayList", "Set", "HashSet", "LinkedHashSet", "LinkedList", "Stack", "TreeSet", "Vector"]
- fun maps: Array[String] is cached do return ["Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
- fun has_generic_params: Bool do return not generic_params == null
fun is_primitive_array: Bool do return array_dimension > 0
+
+ fun has_generic_params: Bool do return not generic_params == null
fun full_id: String do return identifier.join(".")
- fun id: String do return identifier.last
+ fun id: String do return identifier.last.replace("$", "")
- fun return_cast: String
- do
- if self.has_generic_params then
- return converter.cast_as_return(self.generic_params[0].id)
- end
+ init(converter: JavaTypeConverter) do self.converter = converter
- return converter.cast_as_return(self.id)
- end
+ fun return_cast: String do return converter.cast_as_return(self.id)
fun param_cast: String
do
var type_id = converter.to_nit_type(self.id)
if type_id == null then
- nit_type = new NitType(self.full_id)
+ nit_type = self.extern_name
nit_type.is_complete = false
else
nit_type = new NitType(type_id)
var temp_type = converter.to_nit_type(self.id)
if temp_type == null then
- temp_type = self.full_id
+ temp = self.extern_name
nit_type.is_complete = false
+ if temp.mod != null then nit_type.mod = temp.mod
+ else
+ temp = new NitType(temp_type)
end
-
- temp = new NitType(temp_type)
else
temp = new NitType("Array")
end
fun is_map: Bool do return maps.has(self.id)
+ fun is_wrapped: Bool do return find_extern_class != null
+
+ fun extern_name: NitType
+ do
+ if is_wrapped then return new NitType.with_module(find_extern_class.as(not null).first, find_extern_class.as(not null).second)
+
+ var name = "Native" + extern_class_name.join("")
+ var nit_type: NitType
+ if self.is_primitive_array then
+ nit_type = new NitType.with_generic_params("Array", name)
+ else
+ nit_type = new NitType("Native" + extern_class_name.join(""))
+ end
+ nit_type.is_complete = false
+
+ return nit_type
+ end
+
+ fun to_cast(jtype: String, is_param: Bool): String
+ do
+ if is_param then
+ return converter.cast_as_param(jtype)
+ end
+
+ return converter.cast_as_return(jtype)
+ end
+
redef fun to_s: String
do
var id = self.full_id
return id
end
- fun to_cast(jtype: String, is_param: Bool): String
+ # To fully qualified package name
+ # Cuts the primitive array `[]`
+ fun to_package_name: String
do
- if is_param then
- return converter.cast_as_param(jtype)
+ var str = self.to_s
+ var len = str.length
+
+ return str.substring(0, len - (2*array_dimension))
+ end
+
+ fun resolve_types(conversion_map: HashMap[String, Array[String]])
+ do
+ if identifier.length == 1 then
+ var resolved_id = conversion_map.get_or_null(self.id)
+ if resolved_id != null then self.identifier = new Array[String].from(resolved_id)
end
- return converter.cast_as_return(jtype)
+ if self.has_generic_params then
+ for params in generic_params do params.resolve_types(conversion_map)
+ end
+ end
+
+ private fun extern_class_name: Array[String]
+ do
+ var class_name = new Array[String]
+ class_name.add(self.id)
+
+ if not self.has_generic_params then return class_name
+
+ class_name.add "Of"
+
+ for param in generic_params do class_name.add_all param.extern_class_name
+
+ return class_name
+ end
+
+ # Search inside `lib/android` directory for already wrapped classes
+ # If found, contains the class identifier and the Nit Module name
+ var find_extern_class: nullable Couple[String, NitModule] = find_extern_class_fun is lazy
+
+ private fun find_extern_class_fun: nullable Couple[String, NitModule]
+ do
+ var regex = "extern class Native[a-zA-Z1-9]\\\+[ ]\\\+in[ ]\\\+\"Java\"[ ]*`\{[ ]*" + self.to_s + "\\\+[ ]*`\}"
+ var grep = new IProcess("grep", "-r", regex, "{"NIT_DIR".environ}/lib/android/")
+ var to_eat = ["private", "extern", "class"]
+
+ var output = grep.read_line
+
+ var output_class = output.substring_from(output.index_of(':') + 1)
+ var tokens = output_class.split(" ")
+
+ var nclass_name = ""
+
+ for token in tokens do
+ if to_eat.has(token) then continue
+ nclass_name = token
+ break
+ end
+
+ if nclass_name == "" then return null
+
+ var str = output.substring(0, output.search(".nit").from)
+ str = str.substring_from(str.last_index_of('/') + 1)
+ var mod = new NitModule(str)
+
+ return new Couple[String, NitModule](nclass_name, mod)
end
+
+ # Comparison based on fully qualified named and generic params
+ # Ignores primitive array so `a.b.c[][] == a.b.c`
+ redef fun ==(other)
+ do
+ if other isa JavaType then
+ return self.repr == other.repr
+ end
+ return false
+ end
+
+ redef fun hash do return self.repr.hash
+
+ private fun repr: String
+ do
+ var id = self.full_id
+
+ if self.has_generic_params then
+ var gen_list = new Array[String]
+
+ for param in generic_params do
+ gen_list.add(param.to_s)
+ end
+
+ id += "<{gen_list.join(", ")}>"
+ end
+
+ return id
+ end
+
+ fun collections_list: Array[String] is cached do return ["List", "ArrayList", "LinkedList", "Vector", "Set", "SortedSet", "HashSet", "TreeSet", "LinkedHashSet", "Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
+ fun iterable: Array[String] is cached do return ["ArrayList", "Set", "HashSet", "LinkedHashSet", "LinkedList", "Stack", "TreeSet", "Vector"]
+ fun maps: Array[String] is cached do return ["Map", "SortedMap", "HashMap", "TreeMap", "Hashtable", "LinkedHashMap"]
end
class NitType
var arg_id: String
var generic_params: nullable Array[NitType] = null
+ # If this NitType was found in `lib/android`, contains the module name to import
+ var mod: nullable NitModule
+
# Returns `true` if all types have been successfully converted to Nit type
var is_complete: Bool = true
self.identifier = id
end
+ init with_generic_params(id: String, gen_params: String...)
+ do
+ self.init(id)
+ self.generic_params = new Array[NitType]
+ for param in gen_params do self.generic_params.add new NitType(param)
+ end
+
+ init with_module(id: String, mod: NitModule)
+ do
+ self.init(id)
+ self.mod = mod
+ end
+
fun is_map: Bool do return maps.has(self.identifier)
redef fun to_s: String
end
class JavaClass
- var name = new Array[String]
+ var class_type = new JavaType(new JavaTypeConverter)
var attributes = new HashMap[String, JavaType]
var methods = new HashMap[String, Array[JReturnAndParams]]
+ var unknown_types = new HashSet[JavaType]
+ var imports = new HashSet[NitModule]
fun add_method(id: String, return_type: JavaType, params: Array[JavaType])
do
self.params = params
end
end
+
+class NitModule
+ var value: String
+
+ init(str: String) do value = str
+
+ redef fun ==(other): Bool do return self.to_s == other.to_s
+ redef fun to_s: String do return self.value
+ redef fun hash: Int do return self.value.hash
+end