documents.py 4.31 KB
Newer Older
xuebingbing's avatar
xuebingbing committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
""" Management of documents for AXDebugging.
"""

import axdebug, gateways
import pythoncom
from util import _wrap, _wrap_remove, RaiseNotImpl, trace
from win32com.server.util import unwrap
import codecontainer
import contexts
from win32com.server.exception import Exception
import win32api, winerror, os, string, sys

#def trace(*args):
#       pass

def GetGoodFileName(fname):
    if fname[0] != "<":
        return win32api.GetFullPathName(fname)
    return fname

class DebugDocumentProvider(gateways.DebugDocumentProvider):
    def __init__(self, doc):
        self.doc = doc

    def GetName(self, dnt):
        return self.doc.GetName(dnt)

    def GetDocumentClassId(self):
        return self.doc.GetDocumentClassId()

    def GetDocument(self):
        return self.doc

class DebugDocumentText(gateways.DebugDocumentInfo, gateways.DebugDocumentText, gateways.DebugDocument):
    _com_interfaces_ = gateways.DebugDocumentInfo._com_interfaces_ + \
                       gateways.DebugDocumentText._com_interfaces_ + \
                       gateways.DebugDocument._com_interfaces_
    _public_methods_ = gateways.DebugDocumentInfo._public_methods_ + \
                       gateways.DebugDocumentText._public_methods_ + \
                       gateways.DebugDocument._public_methods_
    # A class which implements a DebugDocumentText, using the functionality
    # provided by a codeContainer
    def __init__(self, codeContainer):
        gateways.DebugDocumentText.__init__(self)
        gateways.DebugDocumentInfo.__init__(self)
        gateways.DebugDocument.__init__(self)
        self.codeContainer = codeContainer

    def _Close(self):
        self.docContexts = None
#               self.codeContainer._Close()
        self.codeContainer = None
    # IDebugDocumentInfo
    def GetName(self, dnt):
        return self.codeContainer.GetName(dnt)

    def GetDocumentClassId(self):
        return "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"

    # IDebugDocument has no methods!
    #

    # IDebugDocumentText methods.
    # def GetDocumentAttributes
    def GetSize(self):
#               trace("GetSize")
        return self.codeContainer.GetNumLines(), self.codeContainer.GetNumChars()
    def GetPositionOfLine(self, cLineNumber):
        return self.codeContainer.GetPositionOfLine(cLineNumber)
    def GetLineOfPosition(self, charPos):
        return self.codeContainer.GetLineOfPosition(charPos)
    def GetText(self, charPos, maxChars, wantAttr):
        # Get all the attributes, else the tokenizer will get upset.
        # XXX - not yet!
#               trace("GetText", charPos, maxChars, wantAttr)
        cont = self.codeContainer
        attr = cont.GetSyntaxColorAttributes()
        return cont.GetText(), attr

    def GetPositionOfContext(self, context):
        trace("GetPositionOfContext", context)
        context = unwrap(context)
        return context.offset, context.length

    # Return a DebugDocumentContext.
    def GetContextOfPosition(self, charPos, maxChars):
        # Make one
        doc = _wrap(self, axdebug.IID_IDebugDocument)
        rc = self.codeContainer.GetCodeContextAtPosition(charPos)
        return rc.QueryInterface(axdebug.IID_IDebugDocumentContext)

class CodeContainerProvider:
    """An abstract Python class which provides code containers!

    Given a Python file name (as the debugger knows it by) this will
    return a CodeContainer interface suitable for use.

    This provides a simple base imlpementation that simply supports
    a dictionary of nodes and providers.
    """
    def __init__(self):
        self.ccsAndNodes = {}

    def AddCodeContainer(self, cc, node = None):
        fname = GetGoodFileName(cc.fileName)
        self.ccsAndNodes[fname] = cc, node

    def FromFileName(self, fname):
        cc, node = self.ccsAndNodes.get(GetGoodFileName(fname), (None, None))
#               if cc is None:
#                       print "FromFileName for %s returning None" % fname
        return cc

    def Close(self):
        for cc, node in self.ccsAndNodes.itervalues():
            try:
                # Must close the node before closing the provider
                # as node may make calls on provider (eg Reset breakpoints etc)
                if node is not None:
                    node.Close()
                cc._Close()
            except pythoncom.com_error:
                pass
        self.ccsAndNodes = {}