"""lldb data formatters for clang classes.

Usage
--
import this file in your ~/.lldbinit by adding this line:

command script import /path/to/ClangDataFormat.py

After that, instead of getting this:

(lldb) p Tok.Loc
(clang::SourceLocation) $0 = {
  (unsigned int) ID = 123582
}

you'll get:

(lldb) p Tok.Loc
(clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
"""

import lldb


def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand(
        "type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation"
    )
    debugger.HandleCommand(
        "type summary add -F ClangDataFormat.QualType_summary clang::QualType"
    )


def SourceLocation_summary(srcloc, internal_dict):
    return SourceLocation(srcloc).summary()


def QualType_summary(qualty, internal_dict):
    return QualType(qualty).summary()


class SourceLocation(object):
    def __init__(self, srcloc):
        self.srcloc = srcloc
        self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
        self.frame = srcloc.GetFrame()

    def offset(self):
        return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()

    def isInvalid(self):
        return self.ID == 0

    def isMacro(self):
        return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()

    def isLocal(self, srcmgr_path):
        return self.frame.EvaluateExpression(
            "(%s).isLocalSourceLocation(%s)"
            % (srcmgr_path, getExpressionPath(self.srcloc))
        ).GetValueAsUnsigned()

    def getPrint(self, srcmgr_path):
        print_str = getValueFromExpression(
            self.srcloc, ".printToString(%s)" % srcmgr_path
        )
        return print_str.GetSummary()

    def summary(self):
        if self.isInvalid():
            return "<invalid loc>"
        srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame)
        if srcmgr_path:
            return "%s (offset: %d, %s, %s)" % (
                self.getPrint(srcmgr_path),
                self.offset(),
                "macro" if self.isMacro() else "file",
                "local" if self.isLocal(srcmgr_path) else "loaded",
            )
        return "(offset: %d, %s)" % (
            self.offset(),
            "macro" if self.isMacro() else "file",
        )


class QualType(object):
    def __init__(self, qualty):
        self.qualty = qualty

    def getAsString(self):
        std_str = getValueFromExpression(self.qualty, ".getAsString()")
        return std_str.GetSummary()

    def summary(self):
        desc = self.getAsString()
        if desc == '"NULL TYPE"':
            return "<NULL TYPE>"
        return desc


# Key is a (function address, type name) tuple, value is the expression path for
# an object with such a type name from inside that function.
FramePathMapCache = {}


def findObjectExpressionPath(typename, frame):
    func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
    key = (func_addr, typename)
    try:
        return FramePathMapCache[key]
    except KeyError:
        # print "CACHE MISS"
        path = None
        obj = findObject(typename, frame)
        if obj:
            path = getExpressionPath(obj)
        FramePathMapCache[key] = path
        return path


def findObject(typename, frame):
    def getTypename(value):
        # FIXME: lldb should provide something like getBaseType
        ty = value.GetType()
        if ty.IsPointerType() or ty.IsReferenceType():
            return ty.GetPointeeType().GetName()
        return ty.GetName()

    def searchForType(value, searched):
        tyname = getTypename(value)
        # print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
        if tyname == typename:
            return value
        ty = value.GetType()
        if not (
            ty.IsPointerType()
            or ty.IsReferenceType()
            or
            # FIXME: lldb should provide something like getCanonicalType
            tyname.startswith("llvm::IntrusiveRefCntPtr<")
            or tyname.startswith("llvm::OwningPtr<")
        ):
            return None
        # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
        # and not the canonical one unfortunately.
        if tyname in searched:
            return None
        searched.add(tyname)
        for i in range(value.GetNumChildren()):
            child = value.GetChildAtIndex(i, 0, False)
            found = searchForType(child, searched)
            if found:
                return found

    searched = set()
    value_list = frame.GetVariables(True, True, True, True)
    for val in value_list:
        found = searchForType(val, searched)
        if found:
            return found if not found.TypeIsPointerType() else found.Dereference()


def getValueFromExpression(val, expr):
    return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr)


def getExpressionPath(val):
    stream = lldb.SBStream()
    val.GetExpressionPath(stream)
    return stream.GetData()
