def function_table(parameters, config): qa.LogProcessStart(config, "function_table") link_map = config["link_map"] syntax_map = config["syntax_map"] lines = [] functions = syntax_map["functions"] ordered_functions = sorted(functions) categoryDict = dict() returnTypeDict = dict() functionlist = list() for function in ordered_functions: link = function + "()" if not "`" + link + "`" in link_map: qa.LogMissingDocumentation(config, link, ["No documentation"], "") category = functions[function]["category"] addToDict(categoryDict, category, function) returnType = functions[function]["returnType"] if returnType == "context": returnType = "class" elif returnType in ["ilist", "slist", "rlist"]: returnType = "(i,r,s)list" elif returnType in ["irange", "rrange"]: returnType = "(i,r)range" addToDict(returnTypeDict, returnType, function) lines.append("### Functions by Category\n\n") lines += dictToTable(categoryDict) lines.append("### Functions by Return Type\n\n") lines += dictToTable(returnTypeDict) return lines
def library_include(parameters, config): markdown_lines = [] policy_filename = parameters[0] + ".json" policy_json = config.get(policy_filename) html_name = config.get("context_current_html") qa.LogProcessStart(config, "library_include: %s" % policy_filename) if policy_json == None: policy_path = config[ "project_directory"] + "/_generated/" + policy_filename if not os.path.exists(policy_path): qa.Log(config, "File does not exist: " + policy_path) return markdown_lines policy_json = json.load(open(policy_path, 'r')) config[policy_filename] = policy_json # for all bundles and bodies... for key in policy_json.keys(): element_list = policy_json[key] current_type = None for element in element_list: errorString = [] ignore = False namespace = element["namespace"] if namespace == "default": namespace = None name = element["name"] element_type = element.get("bundleType") if element_type == None: element_type = element.get("bodyType") if element_type == None: qa.Log(config, "element without type: " + name) continue # start a new block for changed types # Assumes that bundles and bodies are grouped by type in library.cf print_type = False if element_type != current_type: current_type = element_type print_type = True prototype = name if namespace: prototype = namespace + ":" + prototype title = prototype link_target = prototype + "()" if not namespace: link_target = parameters[0] + ":" + link_target linkresolver.addLinkToMap(prototype + "()", link_target, html_name + "#" + prototype, config) code_lines = [] documentation_lines = [] documentation_dict = dict() sourceLines = [] sourceLine = -1 try: source_path = element["sourcePath"] source_path = os.path.normpath(source_path) source_file = open(source_path, 'r') sourceLine = element["line"] - 1 # zero-based indexing sourceLines = source_file.readlines()[sourceLine:] except: qa.Log( config, "could not include code for element %s - check %s" % (name, source_path)) if len(sourceLines): headerLines = list() code_lines.append("\n```cf3\n") code_lines.append(sourceLines[0]) del sourceLines[0] in_code = False for line in sourceLines: if not in_code: line = line.lstrip() if line.find("{") == 0: in_code = True else: headerLines.append(line) if in_code: code_lines.append(line) # super-naive parser... if line.find("}\n") == 0: break code_lines.append("\n```\n") # scan comments for doxygen-style documentation if len(headerLines): current_tag = None current_param = None current_line = "" for headerLine in headerLines: if headerLine.find("#") != 0: continue headerLine = headerLine[1:].rstrip() # strip single whitespace, but maintain indentation if headerLine.find(" ") == 0: headerLine = headerLine[1:] if headerLine.lstrip().find("@") == 0: current_param = None headerLine = headerLine.lstrip()[1:] current_tag = headerLine tag_end = headerLine.find(" ") if tag_end != -1: current_tag = current_tag[:tag_end] headerLine = headerLine[tag_end + 1:] documentation_dict[current_tag] = "" if current_tag == None: continue if current_tag == "ignore": ignore = True break if current_tag == "param": if current_param == None: current_param = headerLine[:headerLine.find(" " )] headerLine = headerLine[len(current_param) + 1:] documentation_dict[ "param_" + current_param] = headerLine + "\n" else: documentation_dict[ "param_" + current_param] += headerLine + "\n" else: documentation_dict[ current_tag] += headerLine + "\n" brief = documentation_dict.get("brief", None) if brief: documentation_lines.append("**Description:** ") documentation_lines.append(brief) documentation_lines.append("\n") else: errorString.append("Missing description") return_doc = documentation_dict.get("return", None) if return_doc: documentation_lines.append("**Return value:** ") documentation_lines.append(return_doc) documentation_lines.append("\n") else: # no header lines errorString.append("No documentation") else: # no source lines errorString.append( "No source code or unable to read source code") if ignore: continue arguments = element["arguments"] argument_idx = 0 argument_lines = [] while argument_idx < len(arguments): if argument_idx == 0: prototype += "(" argument_lines.append("**Arguments:**\n\n") argument = arguments[argument_idx] prototype += argument argument_line = "* ```" + argument + "```" # if we have already found documentation for this, use it param_line = documentation_dict.get("param_" + argument) if param_line == None: errorString.append("No documentation for parameter %s" % argument) if param_line != None: argument_line += ": " + param_line # find out where the argument is being used elif key == "bundles": for promise_type in element["promiseTypes"]: promise_type_link = "`" + promise_type["name"] + "`" for context in promise_type["contexts"]: for promise in context["promises"]: promiser = promise["promiser"] if promiser.find("(" + argument + ")") != -1: argument_line += ", used as promiser of type " + promise_type_link argument_line += "\n" else: argument_line += resolveAttribute( promise["attributes"], argument) if len(argument_line): argument_line += " of " + promise_type_link + " promiser *" + promiser + "*" argument_line += "\n" elif key == "bodies": for context in element["contexts"]: argument_line += resolveAttribute( context["attributes"], argument) argument_line += "\n" argument_lines.append(argument_line) argument_idx += 1 if argument_idx == len(arguments): prototype += ")" else: prototype += ", " if print_type: link_map = config["link_map"] if ("`body %s`" % current_type) in link_map: printable_type = "[%s]%s bodies" % ( current_type, link_map["`body %s`" % current_type][0]) elif ("`bundle %s`" % current_type) in link_map: printable_type = "[%s]%s bundles" % ( current_type, link_map["`bundle %s`" % current_type][0]) elif ("`%s`" % current_type) in link_map: printable_type = "[%s]%s %s" % ( current_type, link_map["`%s`" % current_type][0], key) elif key == "bundles": printable_type = "%s [bundles][bundles]" % current_type else: printable_type = current_type markdown_lines.append("### %s\n" % printable_type) markdown_lines.append("\n") markdown_lines.append("#### " + title + " ####\n") markdown_lines.append("\n") markdown_lines.append("**Prototype:** `" + prototype + "`\n") markdown_lines.append("\n") if len(documentation_lines): markdown_lines.append(documentation_lines) markdown_lines.append("\n") if len(argument_lines): markdown_lines.append(argument_lines) markdown_lines.append("\n") if len(code_lines): markdown_lines.append("**Implementation:**\n") markdown_lines.append("\n") markdown_lines.append(code_lines) markdown_lines.append("\n") markdown_lines.append("\n") if len(errorString): locationString = "`in library `" + os.path.relpath( source_path) + "` (%d)" % sourceLine qa.LogMissingDocumentation(config, prototype, errorString, locationString) errorString = [] if len(markdown_lines) == 0: qa.Log(config, "Failure to include " + parameters[0]) return markdown_lines
def syntax_map(parameters, config): qa.LogProcessStart(config, "syntax_map for %s" % parameters[0]) syntax_map = config["syntax_map"] lines = document_syntax_map(syntax_map, parameters[0], config) return lines
def apply(config): qa.LogProcessStart(config, "Applying Link Map") markdown_files = config["markdown_files"] for file in markdown_files: applyLinkMap(file, config)