summaryrefslogtreecommitdiff
path: root/webapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py
diff options
context:
space:
mode:
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py')
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py906
1 files changed, 906 insertions, 0 deletions
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py
new file mode 100755
index 0000000000..b27a10de30
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/tool/modules/comment.py
@@ -0,0 +1,906 @@
+#!/usr/bin/env python
+
+import sys, string, re
+import config, tree, textile
+
+
+
+S_INLINE_COMMENT = "//.*"
+R_INLINE_COMMENT = re.compile("^" + S_INLINE_COMMENT + "$")
+
+R_INLINE_COMMENT_TIGHT = re.compile("^//\S+")
+R_INLINE_COMMENT_PURE = re.compile("^//")
+
+
+
+S_BLOCK_COMMENT = "/\*([^*]|[\n]|(\*+([^*/]|[\n])))*\*+/"
+R_BLOCK_COMMENT = re.compile("^" + S_BLOCK_COMMENT + "$")
+
+R_BLOCK_COMMENT_JAVADOC = re.compile("^/\*\*")
+R_BLOCK_COMMENT_QTDOC = re.compile("^/\*!")
+R_BLOCK_COMMENT_AREA = re.compile("^/\*\n\s*\*\*\*\*\*")
+R_BLOCK_COMMENT_DIVIDER = re.compile("^/\*\n\s*----")
+R_BLOCK_COMMENT_HEADER = re.compile("^/\* \*\*\*\*")
+
+R_BLOCK_COMMENT_TIGHT_START = re.compile("^/\*\S+")
+R_BLOCK_COMMENT_TIGHT_END = re.compile("\S+\*/$")
+R_BLOCK_COMMENT_PURE_START = re.compile("^/\*")
+R_BLOCK_COMMENT_PURE_END = re.compile("\*/$")
+
+R_ATTRIBUTE = re.compile(r'[^{]@(\w+)\s*')
+R_JAVADOC_STARS = re.compile(r'^\s*\*')
+
+
+
+R_NAMED_TYPE = re.compile(r'^\s*(\w+)\s*({([^}]+)})?')
+R_SIMPLE_TYPE = re.compile(r'^\s*({([^}]+)})?')
+
+
+
+
+VARPREFIXES = {
+ "a" : "Array",
+ "b" : "boolean",
+ "d" : "Date",
+ "f" : "Function",
+ "i" : "int",
+ "h" : "Map",
+ "m" : "Map",
+ "n" : "number",
+ "o" : "Object",
+ "r" : "RegExp",
+ "s" : "string",
+ "v" : "var",
+ "w" : "Widget"
+}
+
+VARNAMES = {
+ "a" : "Array",
+ "arr" : "Array",
+
+ "e" : "Event",
+ "ev" : "Event",
+ "evt" : "Event",
+
+ "el" : "Element",
+ "elem" : "Element",
+ "elm" : "Element",
+
+ "ex" : "Exception",
+ "exc" : "Exception",
+
+ "flag" : "boolean",
+ "force" : "boolean",
+
+ "f" : "Function",
+ "func" : "Function",
+
+ "h" : "Map",
+ "hash" : "Map",
+ "map" : "Map",
+
+ "node" : "Node",
+
+ "n" : "number",
+ "num" : "number",
+
+ "o" : "Object",
+ "obj" : "Object",
+
+ "reg" : "RegExp",
+
+ "s" : "string",
+ "str" : "string"
+}
+
+VARDESC = {
+ "propValue" : "Current value",
+ "propOldValue" : "Previous value",
+ "propData" : "Property configuration map"
+}
+
+
+
+
+def outdent(source, indent):
+ return re.compile("\n\s{%s}" % indent).sub("\n", source)
+
+
+
+def indent(source, indent):
+ return re.compile("\n").sub("\n" + (" " * indent), source)
+
+
+
+def correctInline(source):
+ if R_INLINE_COMMENT_TIGHT.match(source):
+ return R_INLINE_COMMENT_PURE.sub("// ", source)
+
+ return source
+
+
+
+def correctBlock(source):
+ if not getFormat(source) in [ "javadoc", "qtdoc" ]:
+ if R_BLOCK_COMMENT_TIGHT_START.search(source):
+ source = R_BLOCK_COMMENT_PURE_START.sub("/* ", source)
+
+ if R_BLOCK_COMMENT_TIGHT_END.search(source):
+ source = R_BLOCK_COMMENT_PURE_END.sub(" */", source)
+
+ return source
+
+
+
+def correct(source):
+ if source.startswith("//"):
+ return correctInline(source)
+ else:
+ return correctBlock(source)
+
+
+
+def isMultiLine(source):
+ return source.find("\n") != -1
+
+
+
+def getFormat(source):
+ if R_BLOCK_COMMENT_JAVADOC.search(source):
+ return "javadoc"
+ elif R_BLOCK_COMMENT_QTDOC.search(source):
+ return "qtdoc"
+ elif R_BLOCK_COMMENT_AREA.search(source):
+ return "area"
+ elif R_BLOCK_COMMENT_DIVIDER.search(source):
+ return "divider"
+ elif R_BLOCK_COMMENT_HEADER.search(source):
+ return "header"
+
+ return "block"
+
+
+
+
+
+
+
+
+def hasThrows(node):
+ if node.type == "throw":
+ return True
+
+ if node.hasChildren():
+ for child in node.children:
+ if hasThrows(child):
+ return True
+
+ return False
+
+
+
+
+def getReturns(node, found):
+ if node.type == "function":
+ pass
+
+ elif node.type == "return":
+ if node.getChildrenLength(True) > 0:
+ val = "var"
+ else:
+ val = "void"
+
+ if node.hasChild("expression"):
+ expr = node.getChild("expression")
+ if expr.hasChild("variable"):
+ var = expr.getChild("variable")
+ if var.getChildrenLength(True) == 1 and var.hasChild("identifier"):
+ val = nameToType(var.getChild("identifier").get("name"))
+ else:
+ val = "var"
+
+ elif expr.hasChild("constant"):
+ val = expr.getChild("constant").get("constantType")
+
+ if val == "number":
+ val = expr.getChild("constant").get("detail")
+
+ elif expr.hasChild("array"):
+ val = "Array"
+
+ elif expr.hasChild("map"):
+ val = "Map"
+
+ elif expr.hasChild("function"):
+ val = "Function"
+
+ elif expr.hasChild("call"):
+ val = "call"
+
+ if not val in found:
+ found.append(val)
+
+ elif node.hasChildren():
+ for child in node.children:
+ getReturns(child, found)
+
+ return found
+
+
+
+def nameToType(name):
+ typ = "var"
+
+ # Evaluate type from name
+ if name in VARNAMES:
+ typ = VARNAMES[name]
+
+ elif len(name) > 1:
+ if name[1].isupper():
+ if name[0] in VARPREFIXES:
+ typ = VARPREFIXES[name[0]]
+
+ return typ
+
+
+
+def nameToDescription(name):
+ desc = "TODOC"
+
+ if name in VARDESC:
+ desc = VARDESC[name]
+
+ return desc
+
+
+
+
+def qt2javadoc(text):
+ attribList = parseText(text, False)
+ res = "/**"
+
+ desc = getAttrib(attribList, "description")["text"]
+
+ if "\n" in desc:
+ res += "\n"
+
+ for line in desc.split("\n"):
+ res += " * %s\n" % line
+
+ res += " "
+
+ else:
+ res += " %s " % desc
+
+ res += "*/"
+
+ return res
+
+
+def parseNode(node):
+ """Takes the last doc comment from the commentsBefore child, parses it and
+ returns a Node representing the doc comment"""
+
+ # Find the last doc comment
+ commentsBefore = node.getChild("commentsBefore", False)
+ if commentsBefore and commentsBefore.hasChildren():
+ for child in commentsBefore.children:
+ if child.type == "comment" and child.get("detail") in [ "javadoc", "qtdoc" ]:
+ return parseText(child.get("text"))
+
+ return []
+
+
+
+def parseText(intext, format=True):
+ # Strip "/**", "/*!" and "*/"
+ intext = intext[3:-2]
+
+ # Strip leading stars in every line
+ text = ""
+ for line in intext.split("\n"):
+ text += R_JAVADOC_STARS.sub("", line).strip() + "\n"
+
+ # Search for attributes
+ desc = { "category" : "description", "text" : "" }
+ attribs = [ desc ]
+ pos = 0
+
+ while True:
+ mtch = R_ATTRIBUTE.search(text, pos)
+
+ if mtch == None:
+ prevText = text[pos:].strip()
+
+ if len(attribs) == 0:
+ desc["text"] = prevText
+ else:
+ attribs[-1]["text"] = prevText
+
+ break
+
+ prevText = text[pos:mtch.start(0)].strip()
+ pos = mtch.end(0)
+
+ if len(attribs) == 0:
+ desc["text"] = prevText
+ else:
+ attribs[-1]["text"] = prevText
+
+ attribs.append({ "category" : mtch.group(1), "text" : "" })
+
+ # parse details
+ for attrib in attribs:
+ parseDetail(attrib, format)
+
+ return attribs
+
+
+
+def parseDetail(attrib, format=True):
+ text = attrib["text"]
+
+ if attrib["category"] in [ "param", "event" ]:
+ mtch = R_NAMED_TYPE.search(text)
+ else:
+ mtch = R_SIMPLE_TYPE.search(text)
+
+ if mtch:
+ text = text[mtch.end(0):]
+
+ if attrib["category"] in [ "param", "event" ]:
+ attrib["name"] = mtch.group(1)
+ # print ">>> NAME: %s" % mtch.group(1)
+ remain = mtch.group(3)
+ else:
+ remain = mtch.group(2)
+
+ if remain != None:
+ defIndex = remain.rfind("?")
+ if defIndex != -1:
+ attrib["default"] = remain[defIndex+1:].strip()
+ remain = remain[0:defIndex].strip()
+ # print ">>> DEFAULT: %s" % attrib["default"]
+
+ typValues = []
+ for typ in remain.split("|"):
+ typValue = typ.strip()
+ arrayIndex = typValue.find("[")
+
+ if arrayIndex != -1:
+ arrayValue = (len(typValue) - arrayIndex) / 2
+ typValue = typValue[0:arrayIndex]
+ else:
+ arrayValue = 0
+
+ typValues.append({ "type" : typValue, "dimensions" : arrayValue })
+
+ if len(typValues) > 0:
+ attrib["type"] = typValues
+ # print ">>> TYPE: %s" % attrib["type"]
+
+ if format:
+ attrib["text"] = formatText(text)
+ else:
+ attrib["text"] = cleanupText(text)
+
+
+
+
+
+
+
+
+def cleanupText(text):
+ #print "============= INTEXT ========================="
+ #print text
+
+ text = text.replace("<p>", "\n")
+ text = text.replace("<br/>", "\n")
+ text = text.replace("<br>", "\n")
+ text = text.replace("</p>", " ")
+
+ newline = False
+ lines = text.split("\n")
+ text = ""
+
+ for line in lines:
+ line = line.strip()
+
+ if line == "":
+ if not newline:
+ newline = True
+
+ else:
+ if text != "":
+ text += "\n"
+
+ if newline:
+ text += "\n"
+ newline = False
+
+ text += line
+
+ #print "============= OUTTEXT ========================="
+ #print text
+
+ return text
+
+
+
+def formatText(text):
+ #print "============= FORMAT:1 ========================="
+ #print text
+
+ # cleanup HTML
+ text = text.replace("<p>", "\n")
+ text = text.replace("<br/>", "\n")
+ text = text.replace("<br>", "\n")
+ text = text.replace("</p>", " ")
+
+ # cleanup wraps
+ text = text.replace("\n\n", "----BREAK----")
+ text = text.replace("\n*", "----UL----")
+ text = text.replace("\n#", "----OL----")
+ text = text.replace("\n", " ")
+ text = text.replace("----BREAK----", "\n\n")
+ text = text.replace("----UL----", "\n*")
+ text = text.replace("----OL----", "\n#")
+
+ #print "============= FORMAT:2 ========================="
+ #print text
+
+ text = textile.textile(unicode(text).encode('utf-8'))
+
+ #print "============= FORMAT:3 ========================="
+ #print text
+
+ return text
+
+
+
+
+
+
+
+
+def getAttrib(attribList, category):
+ for attrib in attribList:
+ if attrib["category"] == category:
+ return attrib
+
+
+
+def getParam(attribList, name):
+ for attrib in attribList:
+ if attrib["category"] == "param":
+ if attrib.has_key("name") and attrib["name"] == name:
+ return attrib
+
+
+
+def attribHas(attrib, key):
+ if attrib != None and attrib.has_key(key) and not attrib[key] in [ "", None ]:
+ return True
+
+ return False
+
+
+
+def splitText(orig, attrib=True):
+ res = ""
+ first = True
+
+ for line in orig.split("\n"):
+ if attrib:
+ if first:
+ res += " %s\n" % line
+ else:
+ res += " * %s\n" % line
+
+ else:
+ res += " * %s\n" % line
+
+ first = False
+
+ if not res.endswith("\n"):
+ res += "\n"
+
+ return res
+
+
+
+def parseType(vtype):
+ typeText = ""
+
+ firstType = True
+ for entry in vtype:
+ if not firstType:
+ typeText += " | "
+
+ typeText += entry["type"]
+
+ if entry.has_key("dimensions") and entry["dimensions"] > 0:
+ typeText += "[]" * entry["dimensions"]
+
+ firstType = False
+
+ return typeText
+
+
+
+
+def fromNode(node, assignType, name, alternative, old=[]):
+ #
+ # description
+ ##############################################################
+ oldDesc = getAttrib(old, "description")
+
+ if attribHas(oldDesc, "text"):
+ newText = oldDesc["text"]
+ else:
+ newText = "{var} TODOC"
+
+ if "\n" in newText:
+ s = "/**\n%s\n-*/" % splitText(newText, False)
+ else:
+ s = "/** %s */" % newText
+
+
+ #
+ # other @attributes
+ ##############################################################
+
+ for attrib in old:
+ cat = attrib["category"]
+
+ if cat != "description":
+ print " * Found unallowed attribute %s in comment for %s" % (cat, name)
+
+ return s
+
+
+
+
+def fromFunction(func, assignType, name, alternative, old=[]):
+ #
+ # open comment
+ ##############################################################
+ s = "/**\n"
+
+
+ #
+ # description
+ ##############################################################
+ oldDesc = getAttrib(old, "description")
+
+ if attribHas(oldDesc, "text"):
+ newText = oldDesc["text"]
+ else:
+ newText = "TODOC"
+
+ s += splitText(newText, False)
+ s += " *\n"
+
+
+
+
+ #
+ # add @type
+ ##############################################################
+ if assignType != None:
+ s += " * @type %s\n" % assignType
+ else:
+ s += " * @type unknown TODOC\n"
+
+
+
+
+ #
+ # add @name
+ ##############################################################
+ if name != None and name != "construct":
+ s += " * @name %s\n" % name
+
+ if name.startswith("__"):
+ s += " * @access private\n"
+ elif name.startswith("_"):
+ s += " * @access protected\n"
+ else:
+ s += " * @access public\n"
+
+
+
+ #
+ # add @alternative
+ ##############################################################
+ oldAlternative = getAttrib(old, "alternative")
+
+ if alternative:
+ if attribHas(oldAlternative, "text"):
+ newText = oldDesc["text"]
+ else:
+ newText = "TODOC"
+
+ s += " * @alternative%s" % splitText(newText)
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+ elif oldAlternative:
+ print " * Removing old @alternative for %s" % name
+
+
+
+
+ #
+ # add @abstract
+ ##############################################################
+ oldAbstract = getAttrib(old, "abstract")
+
+ first = func.getChild("body").getChild("block").getFirstChild(False, True)
+ abstract = first and first.type == "throw"
+
+ if abstract:
+ if attribHas(oldAbstract, "text"):
+ newText = oldDesc["text"]
+ else:
+ newText = ""
+
+ s += " * @abstract%s" % splitText(newText)
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+ elif oldAbstract:
+ print " * Removing old @abstract for %s" % name
+
+
+
+
+
+
+ #
+ # add @param
+ ##############################################################
+ params = func.getChild("params")
+ if params.hasChildren():
+ for child in params.children:
+ if child.type == "variable":
+ newName = child.getChild("identifier").get("name")
+ newType = newTypeText = nameToType(newName)
+ newDefault = ""
+ newText = nameToDescription(newName)
+
+ oldParam = getParam(old, newName)
+
+ # Get type and text from old content
+ if oldParam:
+ if attribHas(oldParam, "type"):
+ newTypeText = parseType(oldParam["type"])
+
+ if attribHas(oldParam, "defaultValue"):
+ newDefault = oldParam["defaultValue"]
+
+ if attribHas(oldParam, "text"):
+ newText = oldParam["text"].strip()
+
+ s += " * @param %s {%s%s}%s" % (newName, newTypeText, newDefault, splitText(newText))
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+
+
+
+
+ #
+ # add @return
+ ##############################################################
+ if name != "construct":
+ oldReturn = getAttrib(old, "return")
+
+ newType = "void"
+ newText = ""
+
+ # Get type and text from old content
+ if oldReturn:
+ if attribHas(oldReturn, "type"):
+ newType = parseType(oldReturn["type"])
+
+ if attribHas(oldReturn, "text"):
+ newText = oldReturn["text"].strip()
+
+ # Try to autodetect the type
+ if newType == "void":
+ returns = getReturns(func.getChild("body"), [])
+
+ if len(returns) > 0:
+ newType = " | ".join(returns)
+ elif name != None and name.startswith("is") and name[3].isupper():
+ newType = "boolean"
+
+ # Add documentation hint in non void cases
+ if newType != "void" and newText == "":
+ newText = "TODOC"
+
+ s += " * @return {%s}%s" % (newType, splitText(newText))
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+
+
+
+
+
+ #
+ # add @throws
+ ##############################################################
+ oldThrows = getAttrib(old, "throws")
+
+ if hasThrows(func):
+ if oldThrows and attribHas(oldThrows, "text"):
+ newText = oldThrows["text"]
+ elif abstract:
+ newText = "the abstract function warning."
+ else:
+ newText = "TODOC"
+
+ s += " * @throws%s" % splitText(newText)
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+ elif oldThrows:
+ print " * Removing old @throw attribute in comment for %s" % name
+
+
+
+
+ #
+ # other @attributes
+ ##############################################################
+
+ for attrib in old:
+ cat = attrib["category"]
+
+ if cat in [ "see", "author", "deprecated", "exception", "since", "version", "abstract", "overridden" ]:
+ s += " * @%s" % cat
+
+ if attribHas(attrib, "text"):
+ s += splitText(attrib["text"])
+
+ if not s.endswith("\n"):
+ s += "\n"
+
+ elif not cat in [ "name", "access", "membership", "alternative", "param", "return", "throws", "description" ]:
+ print " * Found unallowed attribute %s in comment for %s" % (cat, name)
+
+
+
+
+
+ #
+ # close comment
+ ##############################################################
+ s += " */"
+
+ return s
+
+
+
+def fill(node):
+ if node.type in [ "comment", "commentsBefore", "commentsAfter" ]:
+ return
+
+ if node.hasParent():
+ target = node
+
+ if node.type == "function":
+ name = node.get("name", False)
+ else:
+ name = ""
+
+ alternative = False
+ assignType = None
+
+ if name != None:
+ assignType = "function"
+
+ # move to hook operation
+ while target.parent.type in [ "first", "second", "third" ] and target.parent.parent.type == "operation" and target.parent.parent.get("operator") == "HOOK":
+ alternative = True
+ target = target.parent.parent
+
+ # move comment to assignment
+ while target.parent.type == "right" and target.parent.parent.type == "assignment":
+ target = target.parent.parent
+ if target.hasChild("left"):
+ left = target.getChild("left")
+ if left and left.hasChild("variable"):
+ var = left.getChild("variable")
+ last = var.getLastChild(False, True)
+ if last and last.type == "identifier":
+ name = last.get("name")
+ assignType = "object"
+
+ for child in var.children:
+ if child.type == "identifier":
+ if child.get("name") in [ "prototype", "Proto" ]:
+ assignType = "member"
+ elif child.get("name") in [ "class", "base", "Class" ]:
+ assignType = "static"
+
+ elif target.parent.type == "definition":
+ name = target.parent.get("identifier")
+ assignType = "definition"
+
+ # move to definition
+ if target.parent.type == "assignment" and target.parent.parent.type == "definition" and target.parent.parent.parent.getChildrenLength(True) == 1:
+ target = target.parent.parent.parent
+ assignType = "function"
+
+
+ # move comment to keyvalue
+ if target.parent.type == "value" and target.parent.parent.type == "keyvalue":
+ target = target.parent.parent
+ name = target.get("key")
+ assignType = "map"
+
+ if name == "construct":
+ assignType = "constructor"
+
+ if target.parent.type == "map" and target.parent.parent.type == "value" and target.parent.parent.parent.type == "keyvalue":
+ paname = target.parent.parent.parent.get("key")
+
+ if paname == "members":
+ assignType = "member"
+
+ elif paname == "statics":
+ assignType = "static"
+
+ # filter stuff, only add comments to member and static values and to all functions
+ if assignType in [ "member", "static" ] or node.type == "function":
+
+ if not hasattr(target, "documentationAdded") and target.parent.type != "params":
+ old = []
+
+ # create commentsBefore
+ if target.hasChild("commentsBefore"):
+ commentsBefore = target.getChild("commentsBefore")
+
+ if commentsBefore.hasChild("comment"):
+ for child in commentsBefore.children:
+ if child.get("detail") in [ "javadoc", "qtdoc" ]:
+ old = parseText(child.get("text"), False)
+ commentsBefore.removeChild(child)
+ break
+
+ else:
+ commentsBefore = tree.Node("commentsBefore")
+ target.addChild(commentsBefore)
+
+ # create comment node
+ commentNode = tree.Node("comment")
+
+ if node.type == "function":
+ commentNode.set("text", fromFunction(node, assignType, name, alternative, old))
+ else:
+ commentNode.set("text", fromNode(node, assignType, name, alternative, old))
+
+ commentNode.set("detail", "javadoc")
+ commentNode.set("multiline", True)
+
+ commentsBefore.addChild(commentNode)
+
+ # in case of alternative methods, use the first one, ignore the others
+ target.documentationAdded = True
+
+
+
+
+
+ if node.hasChildren():
+ for child in node.children:
+ fill(child)