'Find class, function and method definitions and their location.'

def find_tags(self):

    if (self.tags is not None):
        return self.tags
    self.tokenize()
    result = {}
    namespace = []
    stack = []
    indent = 0
    defline = False
    expect_indent = False
    def tokeniter(ignore=(token.COMMENT, token.NL)):
        for tokentup in self.tokens:
            if (tokentup[0] not in ignore):
                (yield tokentup)
    tokeniter = tokeniter()
    for (type, tok, spos, epos, line) in tokeniter:
        if expect_indent:
            if (type != token.INDENT):
                assert stack
                (dtype, fullname, startline, _) = stack.pop()
                endline = epos[0]
                namespace.pop()
                result[fullname] = (dtype, startline, endline)
            expect_indent = False
        if (tok in ('def', 'class')):
            name = tokeniter.next()[1]
            namespace.append(name)
            fullname = '.'.join(namespace)
            stack.append((tok, fullname, spos[0], indent))
            defline = True
        elif (type == token.INDENT):
            expect_indent = False
            indent += 1
        elif (type == token.DEDENT):
            indent -= 1
            if (stack and (indent == stack[(-1)][3])):
                (dtype, fullname, startline, _) = stack.pop()
                endline = spos[0]
                namespace.pop()
                result[fullname] = (dtype, startline, endline)
        elif (type == token.NEWLINE):
            if defline:
                defline = False
                expect_indent = True
    self.tags = result
    return result
