java: generated code to have javadoc

This commit is contained in:
Ahmed Ashour
2019-06-05 12:44:03 +02:00
parent d6d4571628
commit 5c56b8ce92
14 changed files with 222 additions and 54 deletions
+175 -22
View File
@@ -3,6 +3,7 @@
import sys, re, os.path, errno, fnmatch
import json
import logging
import codecs
from shutil import copyfile
from pprint import pformat
from string import Template
@@ -105,14 +106,19 @@ class GeneralInfo():
self.params={}
self.annotation=[]
if type == "class":
docstring="// C++: class " + self.name + "\n//javadoc: " + self.name
docstring="// C++: class " + self.name + "\n"
else:
docstring=""
if len(decl)>5 and decl[5]:
#logging.info('docstring: %s', decl[5])
if re.search("(@|\\\\)deprecated", decl[5]):
doc = decl[5]
#logging.info('docstring: %s', doc)
if re.search("(@|\\\\)deprecated", doc):
self.annotation.append("@Deprecated")
docstring += sanitize_java_documentation_string(doc, type)
self.docstring = docstring
def parseName(self, name, namespaces):
@@ -263,7 +269,7 @@ class ClassInfo(GeneralInfo):
def initCodeStreams(self, Module):
self.j_code = StringIO()
self.jn_code = StringIO()
self.cpp_code = StringIO();
self.cpp_code = StringIO()
if self.base:
self.j_code.write(T_JAVA_START_INHERITED)
else:
@@ -293,7 +299,7 @@ class ClassInfo(GeneralInfo):
jname = self.jname,
imports = "\n".join(self.getAllImports(M)),
docs = self.docstring,
annotation = "\n".join(self.annotation),
annotation = "\n" + "\n".join(self.annotation) if self.annotation else "",
base = self.base)
def generateCppCode(self):
@@ -481,7 +487,7 @@ class JavaWrapperGenerator(object):
content = f.read()
if content == buf:
return
with open(path, "wt") as f:
with codecs.open(path, "w", "utf-8") as f:
f.write(buf)
updated_files += 1
@@ -495,7 +501,7 @@ class JavaWrapperGenerator(object):
self.add_class( ['class ' + self.Module, '', [], []] ) # [ 'class/struct cname', ':bases', [modlist] [props] ]
# scan the headers and build more descriptive maps of classes, consts, functions
includes = [];
includes = []
for hdr in common_headers:
logging.info("\n===== Common header : %s =====", hdr)
includes.append('#include "' + hdr + '"')
@@ -714,7 +720,7 @@ class JavaWrapperGenerator(object):
fi.jname + "(" + ", ".join(j_args) + ")"
logging.info("java: " + j_signature)
if(j_signature in j_signatures):
if j_signature in j_signatures:
if args:
args.pop()
continue
@@ -730,20 +736,51 @@ class JavaWrapperGenerator(object):
type = type_dict[fi.ctype].get("jn_type", "double[]"),
name = fi.jname + '_' + str(suffix_counter),
args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], normalize_field_name(a.name)) for a in jn_args])
) );
) )
# java part:
#java doc comment
f_name = fi.jname
if fi.classname:
f_name = fi.classname + "::" + fi.jname
java_doc = "//javadoc: " + f_name + "(%s)" % ", ".join([a.name for a in args if a.ctype])
j_code.write(" "*4 + java_doc + "\n")
if fi.docstring:
lines = StringIO(fi.docstring)
for line in lines:
lines = fi.docstring.splitlines()
returnTag = False
javadocParams = []
toWrite = []
inCode = False
for index, line in enumerate(lines):
p0 = line.find("@param")
if p0 != -1:
p0 += 7
p1 = line.find(' ', p0)
p1 = len(line) if p1 == -1 else p1
name = line[p0:p1]
javadocParams.append(name)
for arg in j_args:
if arg.endswith(" " + name):
toWrite.append(line);
break
else:
if "<code>" in line:
inCode = True
if "</code>" in line:
inCode = False
if "@return " in line:
returnTag = True
if (not inCode and toWrite and not toWrite[-1] and
line and not line.startswith("\\") and not line.startswith("<ul>") and not line.startswith("@param")):
toWrite.append("<p>");
if index == len(lines) - 1:
for arg in j_args:
name = arg[arg.rfind(' ') + 1:]
if not name in javadocParams:
toWrite.append(" * @param " + name + " automatically generated");
if type_dict[fi.ctype]["j_type"] and not returnTag and fi.ctype != "void":
toWrite.append(" * @return automatically generated");
toWrite.append(line);
for line in toWrite:
j_code.write(" "*4 + line + "\n")
if fi.annotation:
j_code.write(" "*4 + "\n".join(fi.annotation) + "\n")
@@ -770,7 +807,7 @@ class JavaWrapperGenerator(object):
j_epilogue.append('Converters.Mat_to_' + ret_type + '(retValMat, retVal);')
ret = "return retVal;"
elif ret_type.startswith("Ptr_"):
constructor = type_dict[ret_type]["j_type"] + ".__fromPtr__(";
constructor = type_dict[ret_type]["j_type"] + ".__fromPtr__("
if j_epilogue:
ret_val = type_dict[fi.ctype]["j_type"] + " retVal = " + constructor
else:
@@ -787,14 +824,14 @@ class JavaWrapperGenerator(object):
ret_val = "nativeObj = "
ret = ""
elif self.isWrapped(ret_type): # wrapped class
constructor = self.getClass(ret_type).jname + "(";
constructor = self.getClass(ret_type).jname + "("
if j_epilogue:
ret_val = type_dict[ret_type]["j_type"] + " retVal = new " + constructor
else:
ret_val = "return new " + constructor
tail = ")"
elif "jn_type" not in type_dict[ret_type]:
constructor = type_dict[ret_type]["j_type"] + "(";
constructor = type_dict[ret_type]["j_type"] + "("
if j_epilogue:
ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + constructor
else:
@@ -806,7 +843,7 @@ class JavaWrapperGenerator(object):
static = fi.static
j_code.write( Template(
""" public $static$j_type $j_name($j_args) {$prologue
""" public $static$j_type$j_name($j_args) {$prologue
$ret_val$jn_name($jn_args_call)$tail;$epilogue$ret
}
@@ -818,7 +855,7 @@ class JavaWrapperGenerator(object):
prologue = "\n " + "\n ".join(j_prologue) if j_prologue else "",
epilogue = "\n " + "\n ".join(j_epilogue) if j_epilogue else "",
static = static + " " if static else "",
j_type=type_dict[fi.ctype]["j_type"],
j_type=type_dict[fi.ctype]["j_type"] + " " if type_dict[fi.ctype]["j_type"] else "",
j_name=fi.jname,
j_args=", ".join(j_args),
jn_name=fi.jname + '_' + str(suffix_counter),
@@ -1129,6 +1166,122 @@ def copy_java_files(java_files_dir, java_base_path, default_package_path='org/op
copyfile(src, dest)
updated_files += 1
def sanitize_java_documentation_string(doc, type):
if type == "class":
doc = doc.replace("@param ", "")
doc = re.sub(re.compile('\\\\f\\$(.*?)\\\\f\\$', re.DOTALL), '\\(' + r'\1' + '\\)', doc)
doc = re.sub(re.compile('\\\\f\\[(.*?)\\\\f\\]', re.DOTALL), '\\(' + r'\1' + '\\)', doc)
doc = re.sub(re.compile('\\\\f\\{(.*?)\\\\f\\}', re.DOTALL), '\\(' + r'\1' + '\\)', doc)
doc = doc.replace("&", "&amp;") \
.replace("\\<", "&lt;") \
.replace("\\>", "&gt;") \
.replace("<", "&lt;") \
.replace(">", "&gt;") \
.replace("$", "$$") \
.replace("@anchor", "") \
.replace("@brief ", "").replace("\\brief ", "") \
.replace("@cite", "CITE:") \
.replace("@code{.cpp}", "<code>") \
.replace("@code{.txt}", "<code>") \
.replace("@code", "<code>") \
.replace("@copydoc", "") \
.replace("@copybrief", "") \
.replace("@date", "") \
.replace("@defgroup", "") \
.replace("@details ", "") \
.replace("@endcode", "</code>") \
.replace("@endinternal", "") \
.replace("@file", "") \
.replace("@include", "INCLUDE:") \
.replace("@ingroup", "") \
.replace("@internal", "") \
.replace("@overload", "") \
.replace("@param[in]", "@param") \
.replace("@param[out]", "@param") \
.replace("@ref", "REF:") \
.replace("@returns", "@return") \
.replace("@sa", "SEE:") \
.replace("@see", "SEE:") \
.replace("@snippet", "SNIPPET:") \
.replace("@todo", "TODO:") \
.replace("@warning ", "WARNING: ")
doc = re.sub(re.compile('\\*\\*([^\\*]+?)\\*\\*', re.DOTALL), '<b>' + r'\1' + '</b>', doc)
lines = doc.splitlines()
lines = list(map(lambda x: x[x.find('*'):].strip() if x.lstrip().startswith("*") else x, lines))
listInd = [];
indexDiff = 0;
for index, line in enumerate(lines[:]):
if line.strip().startswith("-"):
i = line.find("-")
if not listInd or i > listInd[-1]:
lines.insert(index + indexDiff, " "*len(listInd) + "<ul>")
indexDiff += 1
listInd.append(i);
lines.insert(index + indexDiff, " "*len(listInd) + "<li>")
indexDiff += 1
elif i == listInd[-1]:
lines.insert(index + indexDiff, " "*len(listInd) + "</li>")
indexDiff += 1
lines.insert(index + indexDiff, " "*len(listInd) + "<li>")
indexDiff += 1
elif len(listInd) > 1 and i == listInd[-2]:
lines.insert(index + indexDiff, " "*len(listInd) + "</li>")
indexDiff += 1
del listInd[-1]
lines.insert(index + indexDiff, " "*len(listInd) + "</ul>")
indexDiff += 1
lines.insert(index + indexDiff, " "*len(listInd) + "<li>")
indexDiff += 1
else:
lines.insert(index + indexDiff, " "*len(listInd) + "</li>")
indexDiff += 1
del listInd[-1]
lines.insert(index + indexDiff, " "*len(listInd) + "</ul>")
indexDiff += 1
lines.insert(index + indexDiff, " "*len(listInd) + "<ul>")
indexDiff += 1
listInd.append(i);
lines.insert(index + indexDiff, " "*len(listInd) + "<li>")
indexDiff += 1
lines[index + indexDiff] = lines[index + indexDiff][0:i] + lines[index + indexDiff][i + 1:]
else:
if listInd and (not line or line == "*" or line.startswith("@note")):
lines.insert(index + indexDiff, " "*len(listInd) + "</li>")
indexDiff += 1
del listInd[-1]
lines.insert(index + indexDiff, " "*len(listInd) + "</ul>")
indexDiff += 1
i = len(listInd) - 1
for value in enumerate(listInd):
lines.append(" "*i + " </li>")
lines.append(" "*i + "</ul>")
i -= 1;
lines = list(map(lambda x: "* " + x[1:].strip() if x.startswith("*") and x != "*" else x, lines))
lines = list(map(lambda x: x if x.startswith("*") else "* " + x if x and x != "*" else "*", lines))
lines = list(map(lambda x: x
.replace("@note", "<b>Note:</b>")
, lines))
lines = list(map(lambda x: re.sub('@b ([\\w:]+?)\\b', '<b>' + r'\1' + '</b>', x), lines))
lines = list(map(lambda x: re.sub('@c ([\\w:]+?)\\b', '<tt>' + r'\1' + '</tt>', x), lines))
lines = list(map(lambda x: re.sub('`(.*?)`', "{@code " + r'\1' + '}', x), lines))
lines = list(map(lambda x: re.sub('@p ([\\w:]+?)\\b', '{@code ' + r'\1' + '}', x), lines))
hasValues = False
for line in lines:
if line != "*":
hasValues = True
break
return "/**\n " + "\n ".join(lines) + "\n */" if hasValues else ""
if __name__ == "__main__":
# initialize logger