Example #1
0
def GenerateTags(buff):
    """Create a DocStruct object that represents a Shell Script
    @param buff: a file like buffer object (StringIO)

    """
    rtags = taglib.DocStruct()
    rtags.SetElementDescription('function', "Function Definitions")

    for lnum, line in enumerate(buff):
        line = line.strip()

        # Skip comment and empty lines
        if line.startswith(u"#") or not line:
            continue

        # Check Regular Function Defs
        if parselib.IsToken(line, 0, u'function'):
            parts = line.split()
            plen = len(parts)
            if plen >= 2 and parselib.IsGoodName(parts[1]):
                if plen == 2 or parts[2] == u"{":
                    rtags.AddFunction(taglib.Function(parts[1], lnum))
            continue

        # Check fname () function defs
        if u"(" in line:
            parts = line.split()
            plen = len(parts)
            if plen >= 2 and parselib.IsGoodName(parts[0]):
                if u''.join(parts[1:]).startswith("()"):
                    rtags.AddFunction(taglib.Function(parts[0], lnum))
            else:
                continue

    return rtags
Example #2
0
def GenerateTags(buff):
    """Create a DocStruct object that represents a Python file
    @param buff: a file like buffer object (StringIO)

    """
    rtags = taglib.DocStruct()
    rtags.SetElementDescription('function', "Function Definitions")
    rtags.SetElementDescription('class', "Class Definitions")

    # Variables for managing the state of the parse
    parents = list()
    indent = 0
    fn_indent = 0
    parens = 0  # Paren nesting count
    indocstring = False
    ind_string = False  # Double quote string
    ins_string = False  # Single quote string
    infunction = False
    lastclass = None

    def NotInString():
        """Return whether the current state of the parse is in a string
        or not.

        """
        return not indocstring and not ind_string and not ins_string

    # Do the parse of the text
    for lnum, line in enumerate(buff):
        indent = 0
        idx = 0
        llen = len(line)
        while idx < llen:
            # Check for docstrings
            if not (ind_string or
                    ins_string) and llen >= idx + 3 and line[idx:idx + 3] in [
                        '"""', "'''"
                    ]:
                indocstring = not indocstring
                idx += 3
                continue

            # If end of line or start of comment start next line
            if idx == llen or (line[idx] == u"#" and NotInString()):
                break

            # Check indent sensitive tokens
            if not indocstring and not line[idx].isspace():

                if infunction and indent < fn_indent:
                    infunction = False

                if lastclass is not None:
                    if indent <= lastclass.get('indent', 0):
                        parents = PopScopes(parents, indent)
                        if len(parents):
                            lastclass = parents[-1]
                        else:
                            lastclass = None

                # Check for if in a string or not
                if line[idx] == u"'" and not ind_string and \
                   idx > 0 and line[idx-1] != "\\": # Single string
                    ins_string = not ins_string
                    idx += 1
                elif line[idx] == u'"' and not ins_string and \
                     idx > 0 and line[idx-1] != "\\": # Double String
                    ind_string = not ind_string
                    idx += 1
                else:
                    pass

            # Parse and look for elements to add to the DocStruct
            if not NotInString():
                # Token is in a string so ignore and move on
                idx = idx + 1
            elif line[idx].isspace():
                # Get indent width for current scope
                if idx == 0:
                    indent = (len(line) - len(line.lstrip()))
                    idx += indent
                else:
                    # Non indent space
                    idx += 1
            elif parselib.IsToken(line, idx, u'class'):
                idx += 5
                cname = parselib.GetFirstIdentifier(line[idx:])
                if cname is not None:
                    if lastclass is None:
                        rtags.AddClass(taglib.Class(cname, lnum))
                    # TODO: check for classes defined within classes

                    lastclass = dict(name=cname, indent=indent)
                    parents.append(dict(lastclass))
                    break  # Go to next line
            elif parselib.IsToken(line, idx, u'def'):
                # Function/Method Definition
                idx += 3
                fname = parselib.GetFirstIdentifier(line[idx:])
                if line[idx].isspace() and fname is not None:
                    infunction = True
                    fn_indent = indent + 1
                    if not line[0].isspace() or lastclass is None or \
                       not len(lastclass.get("name", "")):
                        rtags.AddFunction(taglib.Function(fname, lnum))
                    else:
                        lclass = rtags.GetLastClass()
                        if lclass is not None:
                            lclass.AddMethod(
                                taglib.Method(fname, lnum, lclass.GetName()))
                        else:
                            # Something must have failed with the parse so
                            # ignore this element.
                            pass
                    break
            elif not infunction and line[idx] in u"()":
                # Track paren nesting to help with variable parsing
                if line[idx] == u"(":
                    parens += 1
                else:
                    parens -= 1
                idx += 1
            elif not infunction and line[idx] == u"=" and not parens:
                # Check for Global and Class variables
                idx += 1
                if line[idx] != u"=":  # ignore == statements
                    var = line[:idx - 1].strip().split()
                    if len(var) == 1 and parselib.IsGoodName(var[0]):
                        lclass = rtags.GetLastClass()
                        # Check if we are still inside a class def or not
                        if lastclass is not None and lclass is not None:
                            vobj = taglib.Variable(var[0], lnum,
                                                   lclass.GetName())
                            lclass.AddVariable(vobj)
                        else:
                            # Global Scope variable
                            rtags.AddVariable(taglib.Variable(var[0], lnum))
            else:
                # Nothing so skip ahead
                idx += 1

    # Return the document structure object
    return rtags