Beispiel #1
0
class Search:
    Record = Struct.define('Record', node=None, s='', id=0)

    def __init__(self, tree):
        self.records = []
        self.suffixes = []
        self.db = []

        for node in tree.root.descendants():
            if not node._refid is None:
                self.make_index(node)

    def make_index(self, node):
        name = node.qid.lower()

        r = Search.Record(node=node, s=name, id=len(self.records))
        self.records.append(r)

        for i in range(len(name) - 3):
            suffix = name[i:]

            # Determine where to insert the suffix
            idx = bisect.bisect_left(self.suffixes, suffix)

            if idx != len(self.suffixes) and self.suffixes[idx] == suffix:
                self.db[idx].append((r.id, i))
            else:
                self.suffixes.insert(idx, suffix)
                self.db.insert(idx, [(r.id, i)])
Beispiel #2
0
class Example(list):
    Item = Struct.define('Item', text='', classes=None)

    def append(self, text, classes=None):
        if isinstance(classes, basestring):
            classes = [classes]

        list.append(self, Example.Item(text=text, classes=classes))
Beispiel #3
0
class RangeMap(Sorted):
    Item = Struct.define('Item', obj=None, start=0, end=0)

    def __init__(self):
        super(RangeMap, self).__init__(key=lambda x: x.start)

        self.stack = []

    def push(self, obj, start):
        self.stack.append(RangeMap.Item(obj=obj, start=start, end=start))

    def pop(self, end):
        item = self.stack.pop()
        item.end = end

        self.insert(item)

    def insert(self, item, start=None, end=None):
        if not isinstance(item, RangeMap.Item):
            item = RangeMap.Item(obj=item, start=start, end=end)

        self.insert_right(item)

    def find(self, i):
        # Finds object for which i falls in the range of that object
        idx = bisect.bisect_right(self.keys, i)

        # Go back up until falls within end
        while idx > 0:
            idx -= 1

            o = self[idx]

            if i <= o.end:
                return o.obj

        return None
Beispiel #4
0
class Report:
    Coverage = Struct.define('Coverage',
                             name='',
                             documented=[],
                             undocumented=[])

    def __init__(self, tree, options):
        self.tree = tree
        self.options = options

    def indent(self, elem, level=0):
        i = "\n" + "  " * level

        if len(elem):
            if not elem.text or not elem.text.strip():
                elem.text = i + "  "

            for e in elem:
                self.indent(e, level + 1)

                if not e.tail or not e.tail.strip():
                    e.tail = i + "  "
            if not e.tail or not e.tail.strip():
                e.tail = i
        else:
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i

    def make_location(self, loc):
        elem = ElementTree.Element('location')

        if self.options.basedir:
            start = self.options.basedir
        else:
            start = os.curdir

        elem.set('file', os.path.relpath(str(loc.file), start))
        elem.set('line', str(loc.line))
        elem.set('column', str(loc.column))

        return elem

    def arguments(self, root):
        elem = ElementTree.Element('arguments')
        root.append(elem)

        for node in self.tree.all_nodes:
            if not isinstance(node, nodes.Function):
                continue

            if node.access == cindex.CXXAccessSpecifier.PRIVATE:
                continue

            if node.comment is None:
                continue

            # Check documented arguments
            notdocumented = []
            misspelled = []

            cm = node.comment
            argnames = {}

            for name in node.argument_names:
                argnames[name] = False

            for k in cm.params:
                if self._is_undocumented_comment(cm.params[k]):
                    continue

                if k in argnames:
                    argnames[k] = True
                else:
                    misspelled.append(k)

            for k in argnames:
                if not argnames[k]:
                    notdocumented.append(k)

            if node.return_type.typename != 'void' and not hasattr(
                    cm, 'returns'):
                missingret = True
            elif hasattr(cm, 'returns') and self._is_undocumented_comment(
                    cm.returns):
                missingret = True
            else:
                missingret = False

            if len(notdocumented) > 0 or len(misspelled) > 0 or missingret:
                e = ElementTree.Element('function')
                e.set('id', node.qid)
                e.set('name', node.name)

                for loc in node.comment_locations:
                    e.append(self.make_location(loc))

                if missingret:
                    ee = ElementTree.Element('undocumented-return')
                    e.append(ee)

                for ndoc in notdocumented:
                    ee = ElementTree.Element('undocumented')
                    ee.set('name', ndoc)
                    e.append(ee)

                for mis in misspelled:
                    ee = ElementTree.Element('misspelled')
                    ee.set('name', mis)
                    e.append(ee)

                elem.append(e)

    def _is_undocumented_comment(self, cm):
        return not bool(cm)

    def coverage(self, root):
        pertype = {}

        for node in self.tree.all_nodes:
            cname = node.__class__.__name__

            if node.access == cindex.CXXAccessSpecifier.PRIVATE:
                continue

            if not cname in pertype:
                pertype[cname] = Report.Coverage(name=cname.lower())

            if not self._is_undocumented_comment(node.comment):
                pertype[cname].documented.append(node)
            else:
                pertype[cname].undocumented.append(node)

        cov = ElementTree.Element('coverage')
        root.append(cov)

        for item in pertype.values():
            elem = ElementTree.Element('type')
            elem.set('name', item.name)
            elem.set('documented', str(len(item.documented)))
            elem.set('undocumented', str(len(item.undocumented)))

            item.undocumented.sort(key=lambda x: x.qid)

            for undoc in item.undocumented:
                e = ElementTree.Element('undocumented')
                e.set('id', undoc.qid)
                e.set('name', undoc.name)

                for loc in undoc.comment_locations:
                    e.append(self.make_location(loc))

                elem.append(e)

            cov.append(elem)

    def references(self, root):
        elem = ElementTree.Element('references')
        root.append(elem)

        for node in self.tree.all_nodes:
            if node.comment is None:
                continue

            ee = None

            for name in node.comment.docstrings:
                cm = getattr(node.comment, name)

                if not isinstance(cm, dict):
                    cm = {None: cm}

                for k in cm:
                    en = None

                    for component in cm[k].components:
                        if isinstance(component, Comment.UnresolvedReference):
                            if ee is None:
                                ee = ElementTree.Element(node.classname)

                                ee.set('name', node.name)
                                ee.set('id', node.qid)

                                for loc in node.comment_locations:
                                    ee.append(self.make_location(loc))

                                elem.append(ee)

                            if en is None:
                                en = ElementTree.Element('doctype')

                                en.set('name', name)

                                if not k is None:
                                    en.set('component', k)

                                ee.append(en)

                            er = ElementTree.Element('ref')
                            er.set('name', component.orig)
                            en.append(er)

    def generate(self, filename):
        root = ElementTree.Element('report')
        root.set('id', filename)
        root.set('title', 'Documention generator')

        doc = ElementTree.Element('doc')
        doc.text = """
This page provides a documentation coverage report. Any undocumented symbols
are reported here together with the location of where you should document them.

This report contains the following sections:

1. [Coverage](#{0}/coverage): The documented symbols coverage.
2. [Arguments](#{0}/arguments): Errors about undocumented, misspelled function arguments and
return values.
3. [References](#{0}/references): Unresolved cross references.
""".format(filename)

        root.append(doc)

        self.coverage(root)
        self.arguments(root)
        self.references(root)

        return root