Merge: More jwrapper: fix terminology and add a single feature from the TODO list
authorJean Privat <jean@pryen.org>
Fri, 9 Jan 2015 03:03:43 +0000 (22:03 -0500)
committerJean Privat <jean@pryen.org>
Fri, 9 Jan 2015 03:03:43 +0000 (22:03 -0500)
More clean up on jwrapper, improve terminology and add one feature from #794.

Pull-Request: #1086
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Frédéric Vachon <fredvac@gmail.com>

contrib/jwrapper/Makefile
contrib/jwrapper/README.md
contrib/jwrapper/grammar/javap.sablecc
contrib/jwrapper/src/code_generator.nit
contrib/jwrapper/src/javap_visitor.nit
contrib/jwrapper/src/model.nit [moved from contrib/jwrapper/src/types.nit with 92% similarity]

index b554f0d..0932498 100644 (file)
@@ -1,14 +1,22 @@
-default:
-       mkdir -p bin
+all: nitcc grammar bin/jwrapper
+
+nitcc:
        make -C ../nitcc
-       ../nitcc/src/nitcc ./grammar/javap.sablecc
-       ../../bin/nitc ./src/jwrapper.nit -o ./bin/jwrapper
-       mv *.nit ./src/
-       mkdir -p gen
-       mv javap* ./gen/
+
+grammar:
+       ../nitcc/src/nitcc grammar/javap.sablecc
+       mkdir -p src gen
+       mv *.nit src/
+       mv javap* gen/
+
+bin/jwrapper:
+       mkdir -p bin
+       ../../bin/nitc src/jwrapper.nit -o bin/jwrapper
 
 clean:
        rm -f bin/javap_test_parser bin/jwrapper
        rm -f gen/*
        rm -rf .nit_compile/
        rm src/javap_lexer.nit src/javap_parser.nit src/javap_test_parser.nit
+
+.PHONY: grammar bin/jwrapper
index 412392e..da33dd2 100644 (file)
@@ -1,20 +1,23 @@
-# JWRAPPER : Extern classes generator from java .class
-## Description
-jwrapper is a code generator that creates Nit extern classes `in "Java"` from .class files.
+_jwrapper_, an extern class generator from Java class files
 
-## Installation
-jwrapper is designed to be installed from the `contrib` directory of Nit repository. (http://www.nitlanguage.org)
+# Description
+_jwrapper_ automates wrapping Java classes so they can be accessed from Nit code. It generates Nit extern classes by analyzing Java class files.
+
+_jwrapper_ reuse Nit types of already wrapped Java classes by searching in the `lib/java` and `lib/android` folders in the Nit repository. It won't wrap a class that are already is those folders.
+
+# Installation
+_jwrapper_ is designed to be installed from the `contrib` directory of Nit repository. (http://www.nitlanguage.org)
 
 To initiate installation process, use `make` in the `contrib/jwrapper` directory.
 
-jwrapper relies on `nitcc` that will be automatically compiled from `contrib/nitcc`.
+_jwrapper_ relies on `nitcc` that will be automatically compiled from `contrib/nitcc`.
 
-## Usage
-The jwrapper binary can be found under `jwrapper/bin` directory.
+# Usage
+The _jwrapper_ binary can be found under `contrib/jwrapper/bin` directory.
 
-Since jwrapper uses `grep` to find existing libraries, make sure that the environment variable `NIT_DIR` is properly set to your Nit root directory.
+_jwrapper_ uses `grep` to find existing libraries, make sure that the environment variable `NIT_DIR` is properly set to your Nit root directory.
 
-Since jwrapper uses `javap` to extract data from .class files, the JDK7 or higher has to be installed and must be in your `$PATH`. (Older versions of `javap` do not show generic signatures)
+_jwrapper_ uses `javap` to extract data from .class files, the JDK7 or higher has to be installed and must be in your `$PATH`. (Older versions of `javap` do not show generic signatures)
 
 Usage :
 
@@ -28,7 +31,7 @@ The options are :
 
 `-c, --comment`
 
-* When a method contains at least one unknown type, the code generator will comment the whole method and let the client manage it.
+* When a method contains at least one unknown type, the code generator will comment the whole method and let the client manage it. Unknown types are types that doesn't have an equivalent in Nit as of yet.
 
 `-w, --wrap`
 
@@ -38,8 +41,4 @@ The options are :
 
 * Print the help message
 
-Unknown types are types that doesn't have an equivalent in Nit as of yet.
-
-Jwrapper won't wrap a class that already is in the `lib/android` directory.
-
 Can't use both -c and -w together, either you comment unknown types or you wrap them.
index 4e9165a..87dfa12 100644 (file)
@@ -13,12 +13,12 @@ multi_files = class_or_interface*;
 
 class_or_interface = class_declaration | interface_declaration;
 
-class_declaration = class_header '{' field_declaration* '}';
+class_declaration = class_header '{' property_declaration* '}';
 
 class_header = modifier* 'class' full_class_name extends_declaration?
                           implements_declaration? throws_declaration?;
 interface_declaration = modifier* 'interface' full_class_name extends_interface_declaration?
-                                               '{' field_declaration* '}';
+                                               '{' property_declaration* '}';
 
 modifier = 'public'|'private'|'protected'|'static'|'final'|'native'|'synchronized'|'abstract'|'threadsafe'|'transient'|'volatile';
 type = type_specifier '[]'*;
@@ -50,7 +50,7 @@ statement_block = '{' statement* '}';
 variable_id = identifier '[]'*;
 method_id = identifier;
 
-field_declaration = method_declaration | constructor_declaration | variable_declaration | static_declaration | ';';
+property_declaration = method_declaration | constructor_declaration | variable_declaration | static_declaration | ';';
 variable_declaration = modifier* type variable_id throws_declaration? ';';
 method_declaration = modifier* generic_param? type method_id '(' parameter_list? ')' throws_declaration? ';';
 constructor_declaration = modifier* full_class_name '(' parameter_list? ')' throws_declaration? ';';
index 9e997cc..0da3c77 100644 (file)
@@ -17,7 +17,7 @@
 # Services to generate extern class `in "Java"`
 module code_generator
 
-intrude import types
+intrude import model
 
 class CodeGenerator
 
@@ -128,9 +128,9 @@ class CodeGenerator
 
        fun gen_attribute(jid: String, jtype: JavaType): String
        do
-               return "\tvar {jid.to_snake_case}: {jtype.to_nit_type}\n"
+               return "\tvar {jid.to_nit_method_name}: {jtype.to_nit_type}\n"
        end
-       
+
        fun gen_method(jmethod_id: String, nmethod_id: String, jreturn_type: JavaType, jparam_list: Array[JavaType]): String
        do
                var java_params = ""
@@ -138,7 +138,7 @@ class CodeGenerator
                var nit_id = "arg"
                var nit_id_no = 0
                var nit_types = new Array[NitType]
-               var comment = "" 
+               var comment = ""
 
                # Parameters
                for i in [0..jparam_list.length[ do
@@ -177,7 +177,7 @@ class CodeGenerator
                end
 
                # Method identifier
-               var method_id = nmethod_id.to_snake_case
+               var method_id = nmethod_id.to_nit_method_name
                var nit_signature = new Array[String]
 
                nit_signature.add "\tfun {method_id}"
@@ -216,7 +216,7 @@ class CodeGenerator
                        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
-                       temp.add(" in \"Java\" `\{\n{comment}\t\treturn {jreturn_type.return_cast} recv.{jmethod_id}({java_params});\n{comment}\t`\}\n")
+                       temp.add(" in \"Java\" `\{\n{comment}\t\treturn {jreturn_type.return_cast}recv.{jmethod_id}({java_params});\n{comment}\t`\}\n")
                # Methods without return type
                else if jreturn_type.is_void then
                        temp.add(" in \"Java\" `\{\n{comment}\t\trecv.{jmethod_id}({java_params});\n{comment}\t`\}\n")
@@ -251,48 +251,29 @@ class CodeWarehouse
                else
                        imports = """ import {{{ntype}}}.iterator, Iterator[{{{gen_type}}}].is_ok, Iterator[{{{gen_type}}}].next, Iterator[{{{gen_type}}}].item"""
                end
-               
+
                return imports
        end
+end
 
-       private fun create_loop(java_type: JavaType, nit_type: NitType, is_param: Bool, jarray_id, narray_id: String): String
+redef class String
+       # Convert the Java method name `self` to the Nit style
+       #
+       # * Converts to snake case
+       # * Strips `Get` and `Set`
+       # * Add suffix `=` to setters
+       fun to_nit_method_name: String
        do
-               var loop_header = ""
-               var loop_body = ""
-               var gen_type = nit_type.generic_params.join("_")
-
-               if is_param then
-                       if java_type.is_primitive_array then
-                               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((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)) {"""
-                               if nit_type.is_map then
-                                       var key_cast = java_type.to_cast(java_type.generic_params[0].id, true)
-                                       var value_cast = java_type.to_cast(java_type.generic_params[1].id, true)
-                                       loop_body   = """\t\t\t{{{jarray_id}}}[{{{key_cast}}}iterator_of_{{{nit_type.id}}}_key(itr)] = {{{value_cast}}}iterator_of_{{{nit_type.id}}}_item(itr);\n\t\t\titerator_of_{{{gen_type}}}_next(itr);\n\t\t}"""
-                               else
-                                       loop_body   = """\t\t\t{{{jarray_id}}}.add({{{java_type.param_cast}}}iterator_of_{{{nit_type.id}}}_item(itr));\n\t\t\titerator_of_{{{gen_type}}}_next(itr);\n\t\t}"""
-                               end
-                       end
+               var name
+               if self.has_prefix("Get") then
+                       name = self.substring_from(3)
+               else if self.has_prefix("Set") then
+                       name = self.substring_from(3)
+                       name += "="
                else
-                       if nit_type.is_map then
-                               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());"""
-                       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);"""
-                       else
-                               loop_header = "for(int i=0; i < {jarray_id}.length; ++i)"
-                               loop_body   = """\t\t\t{{{nit_type.id}}}_of_{{{gen_type}}}_add({{{narray_id}}}, {{{java_type.return_cast}}}{{{jarray_id}}}[i]);"""
-                       end
+                       name = self
                end
 
-               return loop_header + "\n" + loop_body
+               return name.to_snake_case
        end
 end
index 1ede6f0..9ee4190 100644 (file)
@@ -21,7 +21,7 @@ module javap_visitor
 import javap_test_parser
 import code_generator
 import jtype_converter
-intrude import types
+intrude import model
 
 class JavaVisitor
        super Visitor
@@ -336,11 +336,11 @@ redef class Nimplements_declaration
        end
 end
 
-#                                          #
-#   F I E L D    D E C L A R A T I O N S   #
-#                                          #
+#                                            #
+# P R O P E R T Y    D E C L A R A T I O N S #
+#                                            #
 
-# Method declaration in the field declarations
+# Method declaration
 redef class Nmethod_declaration
        redef fun accept_visitor(v)
        do
@@ -357,7 +357,7 @@ redef class Nmethod_declaration
        end
 end
 
-# Constructor declaration in the field declarations
+# Constructor declaration
 redef class Nconstructor_declaration
        redef fun accept_visitor(v)
        do
@@ -367,7 +367,7 @@ redef class Nconstructor_declaration
        end
 end
 
-# Variable declaration in the field declarations
+# Variable property declaration
 redef class Nvariable_declaration
        redef fun accept_visitor(v)
        do
@@ -382,7 +382,7 @@ redef class Nvariable_declaration
        end
 end
 
-# Static declaration in the field declarations
+# Static property declaration
 redef class Nstatic_declaration
        redef fun accept_visitor(v)
        do
@@ -392,7 +392,7 @@ redef class Nstatic_declaration
        end
 end
 
-# Identifier of the field
+# Identifier of a variable
 redef class Nvariable_id
        redef fun accept_visitor(v)
        do
similarity index 92%
rename from contrib/jwrapper/src/types.nit
rename to contrib/jwrapper/src/model.nit
index 4fb5251..b77c734 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Contains the java and nit type representation used to convert java to nit code
-module types
+module model
 
 import jtype_converter
 
@@ -67,7 +67,7 @@ class JavaType
                end
 
                if not self.has_generic_params then return nit_type
-               
+
                nit_type.generic_params = new Array[NitType]
 
                for param in generic_params do
@@ -123,7 +123,7 @@ class JavaType
                        for i in [0..array_dimension[ do
                                id += "[]"
                        end
-               else if self.has_generic_params then 
+               else if self.has_generic_params then
                        var gen_list = new Array[String]
 
                        for param in generic_params do
@@ -277,7 +277,7 @@ class NitType
        do
                var id = self.identifier
 
-               if self.has_generic_params then 
+               if self.has_generic_params then
                        var gen_list = new Array[String]
 
                        for param in generic_params do
@@ -294,36 +294,36 @@ end
 class JavaClass
        var class_type = new JavaType(new JavaTypeConverter)
        var attributes = new HashMap[String, JavaType]
-       var methods = new HashMap[String, Array[JReturnAndParams]]
+
+       # Methods of this class organized by their name
+       var methods = new HashMap[String, Array[JavaMethod]]
+
        var unknown_types = new HashSet[JavaType]
        var imports = new HashSet[NitModule]
 
        fun add_method(id: String, return_type: JavaType, params: Array[JavaType])
        do
-               var ret_and_params = methods.get_or_default(id, new Array[JReturnAndParams])
-               
-               ret_and_params.add(new JReturnAndParams(return_type, new Array[JavaType].from(params)))
-               methods[id] = ret_and_params
+               var signatures = methods.get_or_default(id, new Array[JavaMethod])
+               signatures.add(new JavaMethod(return_type, new Array[JavaType].from(params)))
+               methods[id] = signatures
        end
 end
 
-class JReturnAndParams
+# A Java method, with its signature
+class JavaMethod
+       # Type returned by the method
        var return_type: JavaType
-       var params: Array[JavaType]
 
-       init(return_type: JavaType, params: Array[JavaType])
-       do
-               self.return_type = return_type
-               self.params = params
-       end
+       # Type of the arguments of the method
+       var params: Array[JavaType]
 end
 
+# A Nit module, use to import the referenced extern classes
 class NitModule
-       var value: String
-
-       init(str: String) do value = str
+       # Name of the module
+       var name: String
 
        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
+       redef fun to_s: String do return self.name
+       redef fun hash: Int do return self.name.hash
 end