[IronPython] Komodo .NET intellisense
Brian Quinlan
brian at sweetapp.com
Wed Aug 25 07:24:31 PDT 2004
Attached is my script for modifying the ActiveState Komodo intellisense
database to provide intellisense for Windows forms. The script presumes
that you've copied
<komodo-dir>\python\Lib\site-packages\codeintel\python.cix TO
<komodo-dir>\python\Lib\site-packages\codeintel\python-orig.cix
Once you've done that, there are three paths that you'll have to change
near the end of the script. Now run the script.
Now you'll have to delete the Komodo database file (or fix my script to
provide correct time stamps) from:
C:\Documents and Settings\Brian Quinlan\Application
Data\ActiveState\Komodo\3.0\<hostname>\codeintel.db
Then launch Komodo and rebuild the Komodo intellisense database (see
"Preferences...").
Let me know if you need any help or what the prebuilt file (it's half a
meg compressed so I'm not going to post it to the list).
Cheers,
Brian
-------------- next part --------------
from System.Reflection import Assembly
from System.Xml import XmlImplementation
import time
def intersect_dicts(d1, d2):
intersect_dict = {}
for key in [k for k in d1 if k in d2]:
if d1[key].ParameterType != d2[key].ParameterType:
print '--> %s %s %s %s' % (d1[key].Name, d1[key].ParameterType, d2[key].Name, d2[key].ParameterType)
intersect_dict[key] = d1[key]
return intersect_dict
def difference_dicts(d1, d2):
diff_dict = {}
for key in [k for k in d1 if k not in d2]:
diff_dict[key] = d1[key]
for key in [k for k in d2 if k not in d1]:
diff_dict[key] = d2[key]
return diff_dict
def _build_signature_and_doc(paramlists):
if len(paramlists) == 0:
return [], '', ''
# build a list containing dictionaries where each dictionary
# represents one signature of an identically named method. The
# dictionary keys are the argument names and the values of
# .NET ParamInfo classes
dicts = []
for params in paramlists:
dicts.append(dict([(param.Name, param) for param in params]))
# determine the intersection and difference between these argument
# lists - the intersection is the "required" paramters and the
# different is the "optional" parameters. This is only an
# approximation used because Komodo only supports one signature
# per method name
intersection_dict = dict(dicts[0])
difference_dict = {}
for d in dicts:
# XXX These don't actually seem to get built correctly
# see MessageBox.Show(
difference_dict = difference_dicts(intersection_dict, d)
intersection_dict = intersect_dicts(intersection_dict, d)
def sorted(params):
params = [(p.Position, p.Name, p) for p in params]
params.sort()
return [p[2] for p in params]
doc = ""
sig = ""
for param in sorted(intersection_dict.values()):
if doc != "":
# assert sig != ""
doc = doc + ", "
sig = sig + ", "
sig = sig + param.Name
doc = doc + str(param.ParameterType)
for param in sorted(difference_dict.values()):
if doc != "":
# assert sig != ""
doc = doc + ", "
sig = sig + ", "
sig = '%s%s?' % (sig, param.Name)
doc = '%s%s?' % (doc, param.ParameterType)
return intersection_dict.keys(), sig, doc
class MethodInfo(object):
def __init__(self, methodinfo):
# XXX need to accept a list of methodinfos with the
# same .Name
self.name = methodinfo.Name
self.args, sig, doc = _build_signature_and_doc(
[methodinfo.GetParameters()])
self.doc = "%s(%s)" % (self.name, doc)
self.signature = "%s(%s)" % (self.name, sig)
class ClassInfo(object):
def __init__(self, typ):
splitname = typ.FullName.split('.')
self.name = splitname[-1]
self.namespace = '.'.join(splitname[:-1])
constructor_param_lists = []
for ctors in typ.GetConstructors():
constructor_param_lists.append(ctors.GetParameters())
self.args, sig, doc = _build_signature_and_doc(constructor_param_lists)
self.doc = "%s(%s)" % (self.name, doc)
self.signature = "%s(%s)" % (self.name, sig)
self.methodsinfo = []
for method in typ.GetMethods():
self.methodsinfo.append(MethodInfo(method))
def create_namespace_from_assembly(assembly):
namespace = {}
types = assembly.GetTypes()
for t in types:
cls = ClassInfo(t)
namespace.setdefault(cls.namespace, []).append(cls)
return namespace
def create_namespace_from_dll(path):
create_namespace_from_assembly(
Assembly.LoadFrom(path))
def merge_namespace_lists(ns_lists):
merged_ns = {}
for ns in ns_lists:
for name, contents in ns.items():
merged_ns.setdefault(name, []).extend(contents)
return merged_ns
def create_ctor_element(document_node, class_info):
init_element = document_node.CreateElement('function')
init_element.SetAttribute('attributes', '__ctor__')
init_element.SetAttribute('name', '__init__')
init_element.SetAttribute('signature', class_info.signature)
doc_element = document_node.CreateElement('doc')
doc_element.AppendChild(document_node.CreateTextNode('XXX not used'))
init_element.AppendChild(doc_element)
return init_element
def create_argument_element(document_node, arg_name):
arg_element = document_node.CreateElement('argument')
arg_element.SetAttribute('name', arg_name)
return arg_element
def append_argument_elements(document_node, node, args):
for arg in args:
node.AppendChild(create_argument_element(document_node, arg))
def create_method_element(document_node, method_info):
function_element = document_node.CreateElement('function')
function_element.SetAttribute('name', method_info.name)
function_element.SetAttribute('signature', method_info.signature)
doc_element = document_node.CreateElement('doc')
doc_element.AppendChild(document_node.CreateTextNode(method_info.doc))
function_element.AppendChild(doc_element)
append_argument_elements(document_node, function_element, method_info.args)
return function_element
def create_class_element(document_node, class_info):
class_element = document_node.CreateElement('class')
class_element.SetAttribute('name', class_info.name)
doc_element = document_node.CreateElement('doc')
doc_element.AppendChild(document_node.CreateTextNode(class_info.doc))
class_element.AppendChild(doc_element)
append_argument_elements(document_node, class_element, class_info.args)
class_element.AppendChild(
create_ctor_element(document_node, class_info))
for method_info in class_info.methodsinfo:
class_element.AppendChild(
create_method_element(document_node, method_info))
return class_element
def create_module_element(document_node, module_name, classes):
module_element = document_node.CreateElement('module')
module_element.SetAttribute('name', module_name)
for c in classes:
module_element.AppendChild(
create_class_element(document_node, c))
return module_element
def modify_and_write_dom(document_node, namespace, path):
file_node = document_node.SelectSingleNode('//file')
modules = namespace.keys()
for module_name, classes in namespace.items():
file_node.AppendChild(
create_module_element(document_node, module_name, classes))
"""
XXX is this needed?
for childnamespace in [n for n in namespaces if namespace in n]:
importelement = doc.CreateElement('import')
moduleelement.AppendChild(importelement)
importelement.SetAttribute('alias', modules[childnamespace][0].name)
importelement.SetAttribute('line', '1')
importelement.SetAttribute('module', childnamespace)
"""
document_node.Save(path)
document_node = XmlImplementation().CreateDocument()
document_node.Load(r'file://C:\Program%20Files\ActiveState%20Komodo%203.0\python\Lib\site-packages\codeintel\python-orig.cix')
assembly = Assembly.LoadFrom(r'C:/WINDOWS/Microsoft.NET/Framework/v1.0.3705/System.Windows.Forms.dll')
namespace = create_namespace_from_assembly(assembly)
# XXX if you want multible assemblies to be loaded, create namespaces for each
# and then use merge_namespace_lists() [not tested]
modify_and_write_dom(
document_node,
namespace,
r'C:\Program Files\ActiveState Komodo 3.0\python\Lib\site-packages\codeintel\python.cix')
More information about the users-ironpython.com
mailing list