mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'param-info' of https://github.com/fitermay/intellij-community
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
'''
|
||||
Id: "$Id$"
|
||||
Copyright: Copyright (c) 2015 Bank of America Merrill Lynch, All Rights Reserved
|
||||
Description:
|
||||
Test:
|
||||
'''
|
||||
# noinspection PyBroadException
|
||||
import types
|
||||
|
||||
from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY3K
|
||||
|
||||
try:
|
||||
import inspect
|
||||
except:
|
||||
try:
|
||||
from _pydev_imps import _pydev_inspect as inspect
|
||||
except:
|
||||
import traceback;
|
||||
|
||||
traceback.print_exc() # Ok, no inspect available (search will not work)from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_PY3K
|
||||
|
||||
from _pydev_bundle._pydev_imports_tipper import signature_from_docstring
|
||||
|
||||
|
||||
def is_bound_method(obj):
|
||||
if isinstance(obj, types.MethodType):
|
||||
return getattr(obj, '__self__', getattr(obj, 'im_self', None)) is not None
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_class_name(instance):
|
||||
return getattr(getattr(instance, "__class__", None), "__name__", None)
|
||||
|
||||
|
||||
def get_bound_class_name(obj):
|
||||
my_self = getattr(obj, '__self__', getattr(obj, 'im_self', None))
|
||||
if my_self is None:
|
||||
return None
|
||||
return get_class_name(my_self)
|
||||
|
||||
|
||||
def get_description(obj):
|
||||
try:
|
||||
ob_call = obj.__call__
|
||||
except:
|
||||
ob_call = None
|
||||
|
||||
if isinstance(obj, type) or type(obj).__name__ == 'classobj':
|
||||
fob = getattr(obj, '__init__', lambda: None)
|
||||
if not isinstance(fob, (types.FunctionType, types.MethodType)):
|
||||
fob = obj
|
||||
elif is_bound_method(ob_call):
|
||||
fob = ob_call
|
||||
else:
|
||||
fob = obj
|
||||
|
||||
argspec = ""
|
||||
fn_name = None
|
||||
fn_class = None
|
||||
if isinstance(fob, (types.FunctionType, types.MethodType)):
|
||||
spec_info = inspect.getfullargspec(fob) if IS_PY3K else inspect.getargspec(fob)
|
||||
argspec = inspect.formatargspec(*spec_info)
|
||||
fn_name = getattr(fob, '__name__', None)
|
||||
if isinstance(obj, type) or type(obj).__name__ == 'classobj':
|
||||
fn_name = "__init__"
|
||||
fn_class = getattr(obj, "__name__", "UnknownClass")
|
||||
elif is_bound_method(obj) or is_bound_method(ob_call):
|
||||
fn_class = get_bound_class_name(obj) or "UnknownClass"
|
||||
|
||||
else:
|
||||
fn_name = getattr(fob, '__name__', None)
|
||||
fn_self = getattr(fob, '__self__', None)
|
||||
if fn_self is not None and not isinstance(fn_self, types.ModuleType):
|
||||
fn_class = get_class_name(fn_self)
|
||||
|
||||
doc_string = get_docstring(ob_call) if is_bound_method(ob_call) else get_docstring(obj)
|
||||
return create_method_stub(fn_name, fn_class, argspec, doc_string)
|
||||
|
||||
|
||||
def create_method_stub(fn_name, fn_class, argspec, doc_string):
|
||||
if fn_name and argspec:
|
||||
doc_string = "" if doc_string is None else doc_string
|
||||
fn_stub = create_function_stub(fn_name, argspec, doc_string, indent=1 if fn_class else 0)
|
||||
if fn_class:
|
||||
expr = fn_class if fn_name == '__init__' else fn_class + '().' + fn_name
|
||||
return create_class_stub(fn_class, fn_stub) + "\n" + expr
|
||||
else:
|
||||
expr = fn_name
|
||||
return fn_stub + "\n" + expr
|
||||
elif doc_string:
|
||||
if fn_name:
|
||||
restored_signature, _ = signature_from_docstring(doc_string, fn_name)
|
||||
if restored_signature:
|
||||
return create_method_stub(fn_name, fn_class, restored_signature, doc_string)
|
||||
return create_function_stub('unknown', '(*args, **kwargs)', doc_string) + '\nunknown'
|
||||
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def get_docstring(obj):
|
||||
if obj is not None:
|
||||
try:
|
||||
if IS_JYTHON:
|
||||
# Jython
|
||||
doc = obj.__doc__
|
||||
if doc is not None:
|
||||
return doc
|
||||
|
||||
from _pydev_bundle import _pydev_jy_imports_tipper
|
||||
|
||||
is_method, infos = _pydev_jy_imports_tipper.ismethod(obj)
|
||||
ret = ''
|
||||
if is_method:
|
||||
for info in infos:
|
||||
ret += info.get_as_doc()
|
||||
return ret
|
||||
|
||||
else:
|
||||
|
||||
doc = inspect.getdoc(obj)
|
||||
if doc is not None:
|
||||
return doc
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
return ''
|
||||
try:
|
||||
# if no attempt succeeded, try to return repr()...
|
||||
return repr(obj)
|
||||
except:
|
||||
try:
|
||||
# otherwise the class
|
||||
return str(obj.__class__)
|
||||
except:
|
||||
# if all fails, go to an empty string
|
||||
return ''
|
||||
|
||||
|
||||
def create_class_stub(class_name, contents):
|
||||
return "class %s(object):\n%s" % (class_name, contents)
|
||||
|
||||
|
||||
def create_function_stub(fn_name, fn_argspec, fn_docstring, indent=0):
|
||||
def shift_right(string, prefix):
|
||||
return ''.join(prefix + line for line in string.splitlines(True))
|
||||
|
||||
fn_docstring = shift_right(inspect.cleandoc(fn_docstring), " " * (indent + 1))
|
||||
ret = '''
|
||||
def %s%s:
|
||||
"""%s"""
|
||||
pass
|
||||
''' % (fn_name, fn_argspec, fn_docstring)
|
||||
ret = ret[1:] # remove first /n
|
||||
ret = ret.replace('\t', " ")
|
||||
if indent:
|
||||
prefix = " " * indent
|
||||
ret = shift_right(ret, prefix)
|
||||
return ret
|
||||
@@ -1,5 +1,5 @@
|
||||
import os.path
|
||||
import inspect
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from _pydev_bundle._pydev_tipper_common import do_find
|
||||
@@ -222,96 +222,7 @@ def generate_imports_tip_for_module(obj_to_complete, dirComps=None, getattr=geta
|
||||
args = '(%s)' % (r)
|
||||
except TypeError:
|
||||
#ok, let's see if we can get the arguments from the doc
|
||||
args = '()'
|
||||
try:
|
||||
found = False
|
||||
if len(doc) > 0:
|
||||
if IS_IPY:
|
||||
#Handle case where we have the situation below
|
||||
#sort(self, object cmp, object key)
|
||||
#sort(self, object cmp, object key, bool reverse)
|
||||
#sort(self)
|
||||
#sort(self, object cmp)
|
||||
|
||||
#Or: sort(self: list, cmp: object, key: object)
|
||||
#sort(self: list, cmp: object, key: object, reverse: bool)
|
||||
#sort(self: list)
|
||||
#sort(self: list, cmp: object)
|
||||
if hasattr(obj, '__name__'):
|
||||
name = obj.__name__+'('
|
||||
|
||||
|
||||
#Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line.
|
||||
lines = doc.splitlines()
|
||||
if len(lines) == 1:
|
||||
c = doc.count(name)
|
||||
if c > 1:
|
||||
doc = ('\n'+name).join(doc.split(name))
|
||||
|
||||
|
||||
major = ''
|
||||
for line in doc.splitlines():
|
||||
if line.startswith(name) and line.endswith(')'):
|
||||
if len(line) > len(major):
|
||||
major = line
|
||||
if major:
|
||||
args = major[major.index('('):]
|
||||
found = True
|
||||
|
||||
|
||||
if not found:
|
||||
i = doc.find('->')
|
||||
if i < 0:
|
||||
i = doc.find('--')
|
||||
if i < 0:
|
||||
i = doc.find('\n')
|
||||
if i < 0:
|
||||
i = doc.find('\r')
|
||||
|
||||
|
||||
if i > 0:
|
||||
s = doc[0:i]
|
||||
s = s.strip()
|
||||
|
||||
#let's see if we have a docstring in the first line
|
||||
if s[-1] == ')':
|
||||
start = s.find('(')
|
||||
if start >= 0:
|
||||
end = s.find('[')
|
||||
if end <= 0:
|
||||
end = s.find(')')
|
||||
if end <= 0:
|
||||
end = len(s)
|
||||
|
||||
args = s[start:end]
|
||||
if not args[-1] == ')':
|
||||
args = args + ')'
|
||||
|
||||
|
||||
#now, get rid of unwanted chars
|
||||
l = len(args) - 1
|
||||
r = []
|
||||
for i in xrange(len(args)):
|
||||
if i == 0 or i == l:
|
||||
r.append(args[i])
|
||||
else:
|
||||
r.append(check_char(args[i]))
|
||||
|
||||
args = ''.join(r)
|
||||
|
||||
if IS_IPY:
|
||||
if args.startswith('(self:'):
|
||||
i = args.find(',')
|
||||
if i >= 0:
|
||||
args = '(self'+args[i:]
|
||||
else:
|
||||
args = '(self)'
|
||||
i = args.find(')')
|
||||
if i > 0:
|
||||
args = args[:i+1]
|
||||
|
||||
except:
|
||||
pass
|
||||
args, doc = signature_from_docstring(doc, getattr(obj, '__name__', None))
|
||||
|
||||
retType = TYPE_FUNCTION
|
||||
|
||||
@@ -350,5 +261,90 @@ def generate_imports_tip_for_module(obj_to_complete, dirComps=None, getattr=geta
|
||||
return ret
|
||||
|
||||
|
||||
def signature_from_docstring(doc, obj_name):
|
||||
args = '()'
|
||||
try:
|
||||
found = False
|
||||
if len(doc) > 0:
|
||||
if IS_IPY:
|
||||
# Handle case where we have the situation below
|
||||
# sort(self, object cmp, object key)
|
||||
# sort(self, object cmp, object key, bool reverse)
|
||||
# sort(self)
|
||||
# sort(self, object cmp)
|
||||
|
||||
# Or: sort(self: list, cmp: object, key: object)
|
||||
# sort(self: list, cmp: object, key: object, reverse: bool)
|
||||
# sort(self: list)
|
||||
# sort(self: list, cmp: object)
|
||||
if obj_name:
|
||||
name = obj_name + '('
|
||||
|
||||
# Fix issue where it was appearing sort(aa)sort(bb)sort(cc) in the same line.
|
||||
lines = doc.splitlines()
|
||||
if len(lines) == 1:
|
||||
c = doc.count(name)
|
||||
if c > 1:
|
||||
doc = ('\n' + name).join(doc.split(name))
|
||||
|
||||
major = ''
|
||||
for line in doc.splitlines():
|
||||
if line.startswith(name) and line.endswith(')'):
|
||||
if len(line) > len(major):
|
||||
major = line
|
||||
if major:
|
||||
args = major[major.index('('):]
|
||||
found = True
|
||||
|
||||
if not found:
|
||||
i = doc.find('->')
|
||||
if i < 0:
|
||||
i = doc.find('--')
|
||||
if i < 0:
|
||||
i = doc.find('\n')
|
||||
if i < 0:
|
||||
i = doc.find('\r')
|
||||
|
||||
if i > 0:
|
||||
s = doc[0:i]
|
||||
s = s.strip()
|
||||
|
||||
# let's see if we have a docstring in the first line
|
||||
if s[-1] == ')':
|
||||
start = s.find('(')
|
||||
if start >= 0:
|
||||
end = s.find('[')
|
||||
if end <= 0:
|
||||
end = s.find(')')
|
||||
if end <= 0:
|
||||
end = len(s)
|
||||
|
||||
args = s[start:end]
|
||||
if not args[-1] == ')':
|
||||
args = args + ')'
|
||||
|
||||
# now, get rid of unwanted chars
|
||||
l = len(args) - 1
|
||||
r = []
|
||||
for i in xrange(len(args)):
|
||||
if i == 0 or i == l:
|
||||
r.append(args[i])
|
||||
else:
|
||||
r.append(check_char(args[i]))
|
||||
|
||||
args = ''.join(r)
|
||||
|
||||
if IS_IPY:
|
||||
if args.startswith('(self:'):
|
||||
i = args.find(',')
|
||||
if i >= 0:
|
||||
args = '(self' + args[i:]
|
||||
else:
|
||||
args = '(self)'
|
||||
i = args.find(')')
|
||||
if i > 0:
|
||||
args = args[:i + 1]
|
||||
|
||||
except:
|
||||
pass
|
||||
return args, doc
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import os
|
||||
|
||||
from _pydev_bundle.pydev_imports import xmlrpclib, _queue, Exec
|
||||
import sys
|
||||
from _pydevd_bundle.pydevd_constants import IS_JYTHON
|
||||
from _pydev_bundle._pydev_calltip_util import get_description
|
||||
from _pydev_imps._pydev_saved_modules import thread
|
||||
from _pydevd_bundle import pydevd_xml
|
||||
from _pydevd_bundle import pydevd_vars
|
||||
from _pydevd_bundle import pydevd_xml
|
||||
from _pydevd_bundle.pydevd_constants import IS_JYTHON
|
||||
from _pydevd_bundle.pydevd_utils import * # @UnusedWildImport
|
||||
import traceback
|
||||
|
||||
#=======================================================================================================================
|
||||
|
||||
# =======================================================================================================================
|
||||
# Null
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
class Null:
|
||||
"""
|
||||
Gotten from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205
|
||||
@@ -54,39 +52,39 @@ class Null:
|
||||
return 0
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
# BaseStdIn
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
class BaseStdIn:
|
||||
def __init__(self, original_stdin=sys.stdin, *args, **kwargs):
|
||||
try:
|
||||
self.encoding = sys.stdin.encoding
|
||||
except:
|
||||
#Not sure if it's available in all Python versions...
|
||||
# Not sure if it's available in all Python versions...
|
||||
pass
|
||||
self.original_stdin = original_stdin
|
||||
|
||||
def readline(self, *args, **kwargs):
|
||||
#sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything
|
||||
#This could happen if the user had done input('enter number).<-- upon entering this, that message would appear,
|
||||
#which is not something we want.
|
||||
# sys.stderr.write('Cannot readline out of the console evaluation\n') -- don't show anything
|
||||
# This could happen if the user had done input('enter number).<-- upon entering this, that message would appear,
|
||||
# which is not something we want.
|
||||
return '\n'
|
||||
|
||||
def isatty(self):
|
||||
return False #not really a file
|
||||
return False # not really a file
|
||||
|
||||
def write(self, *args, **kwargs):
|
||||
pass #not available StdIn (but it can be expected to be in the stream interface)
|
||||
pass # not available StdIn (but it can be expected to be in the stream interface)
|
||||
|
||||
def flush(self, *args, **kwargs):
|
||||
pass #not available StdIn (but it can be expected to be in the stream interface)
|
||||
pass # not available StdIn (but it can be expected to be in the stream interface)
|
||||
|
||||
def read(self, *args, **kwargs):
|
||||
#in the interactive interpreter, a read and a readline are the same.
|
||||
# in the interactive interpreter, a read and a readline are the same.
|
||||
return self.readline()
|
||||
|
||||
def close(self, *args, **kwargs):
|
||||
pass #expected in StdIn
|
||||
pass # expected in StdIn
|
||||
|
||||
def __getattr__(self, item):
|
||||
# it's called if the attribute wasn't found
|
||||
@@ -95,9 +93,9 @@ class BaseStdIn:
|
||||
raise AttributeError("%s has no attribute %s" % (self.original_stdin, item))
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
# StdIn
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
class StdIn(BaseStdIn):
|
||||
'''
|
||||
Object to be added to stdin (to emulate it as non-blocking while the next line arrives)
|
||||
@@ -110,16 +108,18 @@ class StdIn(BaseStdIn):
|
||||
self.host = host
|
||||
|
||||
def readline(self, *args, **kwargs):
|
||||
#Ok, callback into the client to get the new input
|
||||
# Ok, callback into the client to get the new input
|
||||
try:
|
||||
server = xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port))
|
||||
requested_input = server.RequestInput()
|
||||
if not requested_input:
|
||||
return '\n' #Yes, a readline must return something (otherwise we can get an EOFError on the input() call).
|
||||
return '\n' # Yes, a readline must return something (otherwise we can get an EOFError on the input() call).
|
||||
return requested_input
|
||||
except:
|
||||
return '\n'
|
||||
|
||||
def close(self, *args, **kwargs):
|
||||
pass # expected in StdIn
|
||||
|
||||
#=======================================================================================================================
|
||||
# DebugConsoleStdIn
|
||||
@@ -155,9 +155,10 @@ class CodeFragment:
|
||||
if not code_fragment.is_single_line:
|
||||
self.is_single_line = False
|
||||
|
||||
#=======================================================================================================================
|
||||
|
||||
# =======================================================================================================================
|
||||
# BaseInterpreterInterface
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
class BaseInterpreterInterface:
|
||||
def __init__(self, mainThread):
|
||||
self.mainThread = mainThread
|
||||
@@ -206,15 +207,15 @@ class BaseInterpreterInterface:
|
||||
try:
|
||||
help = None
|
||||
if 'pydoc' in sys.modules:
|
||||
pydoc = sys.modules['pydoc'] #Don't import it if it still is not there.
|
||||
pydoc = sys.modules['pydoc'] # Don't import it if it still is not there.
|
||||
|
||||
if hasattr(pydoc, 'help'):
|
||||
#You never know how will the API be changed, so, let's code defensively here
|
||||
# You never know how will the API be changed, so, let's code defensively here
|
||||
help = pydoc.help
|
||||
if not hasattr(help, 'input'):
|
||||
help = None
|
||||
except:
|
||||
#Just ignore any error here
|
||||
# Just ignore any error here
|
||||
pass
|
||||
|
||||
more = False
|
||||
@@ -222,7 +223,7 @@ class BaseInterpreterInterface:
|
||||
sys.stdin = self.create_std_in(debugger, original_in)
|
||||
try:
|
||||
if help is not None:
|
||||
#This will enable the help() function to work.
|
||||
# This will enable the help() function to work.
|
||||
try:
|
||||
try:
|
||||
help.input = sys.stdin
|
||||
@@ -268,7 +269,6 @@ class BaseInterpreterInterface:
|
||||
|
||||
return more
|
||||
|
||||
|
||||
def do_add_exec(self, codeFragment):
|
||||
'''
|
||||
Subclasses should override.
|
||||
@@ -277,7 +277,6 @@ class BaseInterpreterInterface:
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def get_namespace(self):
|
||||
'''
|
||||
Subclasses should override.
|
||||
@@ -286,66 +285,48 @@ class BaseInterpreterInterface:
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def __resolve_reference__(self, text):
|
||||
"""
|
||||
|
||||
def getDescription(self, text):
|
||||
try:
|
||||
obj = None
|
||||
if '.' not in text:
|
||||
:type text: str
|
||||
"""
|
||||
obj = None
|
||||
if '.' not in text:
|
||||
try:
|
||||
obj = self.get_namespace()[text]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if obj is None:
|
||||
try:
|
||||
obj = self.get_namespace()[text]
|
||||
except KeyError:
|
||||
return ''
|
||||
|
||||
else:
|
||||
try:
|
||||
splitted = text.split('.')
|
||||
obj = self.get_namespace()[splitted[0]]
|
||||
for t in splitted[1:]:
|
||||
obj = getattr(obj, t)
|
||||
except:
|
||||
return ''
|
||||
|
||||
if obj is not None:
|
||||
try:
|
||||
if sys.platform.startswith("java"):
|
||||
#Jython
|
||||
doc = obj.__doc__
|
||||
if doc is not None:
|
||||
return doc
|
||||
|
||||
from _pydev_bundle import _pydev_jy_imports_tipper
|
||||
|
||||
is_method, infos = _pydev_jy_imports_tipper.ismethod(obj)
|
||||
ret = ''
|
||||
if is_method:
|
||||
for info in infos:
|
||||
ret += info.get_as_doc()
|
||||
return ret
|
||||
|
||||
else:
|
||||
#Python and Iron Python
|
||||
import inspect #@UnresolvedImport
|
||||
|
||||
doc = inspect.getdoc(obj)
|
||||
if doc is not None:
|
||||
return doc
|
||||
obj = self.get_namespace()['__builtins__'][text]
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
#if no attempt succeeded, try to return repr()...
|
||||
return repr(obj)
|
||||
except:
|
||||
if obj is None:
|
||||
try:
|
||||
#otherwise the class
|
||||
return str(obj.__class__)
|
||||
obj = getattr(self.get_namespace()['__builtins__'], text, None)
|
||||
except:
|
||||
#if all fails, go to an empty string
|
||||
return ''
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return ''
|
||||
pass
|
||||
|
||||
else:
|
||||
try:
|
||||
last_dot = text.rindex('.')
|
||||
parent_context = text[0:last_dot]
|
||||
res = pydevd_vars.eval_in_context(parent_context, self.get_namespace(), self.get_namespace())
|
||||
obj = getattr(res, text[last_dot + 1:])
|
||||
except:
|
||||
pass
|
||||
return obj
|
||||
|
||||
def getDescription(self, text):
|
||||
try:
|
||||
obj = self.__resolve_reference__(text)
|
||||
if obj is None:
|
||||
return ''
|
||||
return get_description(obj)
|
||||
except:
|
||||
return ''
|
||||
|
||||
def do_exec_code(self, code, is_single_line):
|
||||
try:
|
||||
@@ -364,7 +345,6 @@ class BaseInterpreterInterface:
|
||||
def execLine(self, line):
|
||||
return self.do_exec_code(line, True)
|
||||
|
||||
|
||||
def execMultipleLines(self, lines):
|
||||
if IS_JYTHON:
|
||||
for line in lines.split('\n'):
|
||||
@@ -372,9 +352,8 @@ class BaseInterpreterInterface:
|
||||
else:
|
||||
return self.do_exec_code(lines, False)
|
||||
|
||||
|
||||
def interrupt(self):
|
||||
self.buffer = None # Also clear the buffer when it's interrupted.
|
||||
self.buffer = None # Also clear the buffer when it's interrupted.
|
||||
try:
|
||||
if self.interruptable:
|
||||
called = False
|
||||
@@ -412,10 +391,10 @@ class BaseInterpreterInterface:
|
||||
pass
|
||||
|
||||
if not called:
|
||||
if hasattr(thread, 'interrupt_main'): #Jython doesn't have it
|
||||
if hasattr(thread, 'interrupt_main'): # Jython doesn't have it
|
||||
thread.interrupt_main()
|
||||
else:
|
||||
self.mainThread._thread.interrupt() #Jython
|
||||
self.mainThread._thread.interrupt() # Jython
|
||||
return True
|
||||
except:
|
||||
traceback.print_exc()
|
||||
@@ -495,11 +474,11 @@ class BaseInterpreterInterface:
|
||||
Used to show console with variables connection.
|
||||
Always return a frame where the locals map to our internal namespace.
|
||||
'''
|
||||
VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java
|
||||
VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java
|
||||
VIRTUAL_FRAME_ID = "1" # matches PyStackFrameConsole.java
|
||||
VIRTUAL_CONSOLE_ID = "console_main" # matches PyThreadConsole.java
|
||||
if thread_id == VIRTUAL_CONSOLE_ID and frame_id == VIRTUAL_FRAME_ID:
|
||||
f = FakeFrame()
|
||||
f.f_globals = {} #As globals=locals here, let's simply let it empty (and save a bit of network traffic).
|
||||
f.f_globals = {} # As globals=locals here, let's simply let it empty (and save a bit of network traffic).
|
||||
f.f_locals = self.get_namespace()
|
||||
return f
|
||||
else:
|
||||
@@ -527,7 +506,7 @@ class BaseInterpreterInterface:
|
||||
except:
|
||||
# This happens on Jython embedded in host eclipse
|
||||
traceback.print_exc()
|
||||
sys.stderr.write('pydevd is not available, cannot connect\n',)
|
||||
sys.stderr.write('pydevd is not available, cannot connect\n', )
|
||||
|
||||
from _pydev_bundle import pydev_localhost
|
||||
threading.currentThread().__pydevd_id__ = "console_main"
|
||||
@@ -589,9 +568,10 @@ class BaseInterpreterInterface:
|
||||
# it to run in the main thread.
|
||||
self.exec_queue.put(do_enable_gui)
|
||||
|
||||
#=======================================================================================================================
|
||||
|
||||
# =======================================================================================================================
|
||||
# FakeFrame
|
||||
#=======================================================================================================================
|
||||
# =======================================================================================================================
|
||||
class FakeFrame:
|
||||
'''
|
||||
Used to show console with variables connection.
|
||||
|
||||
@@ -139,6 +139,7 @@ CMD_STEP_INTO_MY_CODE = 144
|
||||
CMD_GET_CONCURRENCY_EVENT = 145
|
||||
CMD_SHOW_RETURN_VALUES = 146
|
||||
CMD_INPUT_REQUESTED = 147
|
||||
CMD_GET_DESCRIPTION = 148
|
||||
|
||||
CMD_VERSION = 501
|
||||
CMD_RETURN = 502
|
||||
@@ -193,6 +194,7 @@ ID_TO_MEANING = {
|
||||
'145': 'CMD_GET_CONCURRENCY_EVENT',
|
||||
'146': 'CMD_SHOW_RETURN_VALUES',
|
||||
'147': 'CMD_INPUT_REQUESTED',
|
||||
'148': 'CMD_GET_DESCRIPTION',
|
||||
|
||||
'501': 'CMD_VERSION',
|
||||
'502': 'CMD_RETURN',
|
||||
@@ -700,6 +702,12 @@ class NetCommandFactory:
|
||||
except Exception:
|
||||
return self.make_error_message(seq, get_exception_traceback_str())
|
||||
|
||||
def make_get_description_message(self, seq, payload):
|
||||
try:
|
||||
return NetCommand(CMD_GET_DESCRIPTION, seq, payload)
|
||||
except Exception:
|
||||
return self.make_error_message(seq, get_exception_traceback_str())
|
||||
|
||||
def make_get_frame_message(self, seq, payload):
|
||||
try:
|
||||
return NetCommand(CMD_GET_FRAME, seq, payload)
|
||||
@@ -1135,6 +1143,36 @@ class InternalGetCompletions(InternalThreadCommand):
|
||||
cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error evaluating expression " + exc)
|
||||
dbg.writer.add_command(cmd)
|
||||
|
||||
|
||||
# =======================================================================================================================
|
||||
# InternalGetDescription
|
||||
# =======================================================================================================================
|
||||
class InternalGetDescription(InternalThreadCommand):
|
||||
""" Fetch the variable description stub from the debug console
|
||||
"""
|
||||
|
||||
def __init__(self, seq, thread_id, frame_id, expression):
|
||||
self.sequence = seq
|
||||
self.thread_id = thread_id
|
||||
self.frame_id = frame_id
|
||||
self.expression = expression
|
||||
|
||||
def do_it(self, dbg):
|
||||
""" Get completions and write back to the client
|
||||
"""
|
||||
try:
|
||||
frame = pydevd_vars.find_frame(self.thread_id, self.frame_id)
|
||||
description = pydevd_console.get_description(frame, self.thread_id, self.frame_id, self.expression)
|
||||
description = pydevd_vars.make_valid_xml_value(quote(description, '/>_= \t'))
|
||||
description_xml = '<xml><var name="" type="" value="%s"/></xml>' % description
|
||||
cmd = dbg.cmd_factory.make_get_description_message(self.sequence, description_xml)
|
||||
dbg.writer.add_command(cmd)
|
||||
except:
|
||||
exc = get_exception_traceback_str()
|
||||
cmd = dbg.cmd_factory.make_error_message(self.sequence, "Error in fetching description" + exc)
|
||||
dbg.writer.add_command(cmd)
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# InternalGetBreakpointException
|
||||
#=======================================================================================================================
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
'''An helper file for the pydev debugger (REPL) console
|
||||
'''
|
||||
from code import InteractiveConsole
|
||||
import sys
|
||||
import traceback
|
||||
from code import InteractiveConsole
|
||||
|
||||
from _pydev_bundle import _pydev_completer
|
||||
from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str
|
||||
from _pydevd_bundle.pydevd_vars import make_valid_xml_value
|
||||
from _pydev_bundle.pydev_imports import Exec
|
||||
from _pydevd_bundle.pydevd_io import IOBuf
|
||||
from _pydev_bundle.pydev_console_utils import BaseInterpreterInterface, BaseStdIn
|
||||
from _pydev_bundle.pydev_imports import Exec
|
||||
from _pydev_bundle.pydev_override import overrides
|
||||
from _pydevd_bundle import pydevd_save_locals
|
||||
from _pydevd_bundle.pydevd_io import IOBuf
|
||||
from _pydevd_bundle.pydevd_tracing import get_exception_traceback_str
|
||||
from _pydevd_bundle.pydevd_vars import make_valid_xml_value
|
||||
|
||||
CONSOLE_OUTPUT = "output"
|
||||
CONSOLE_ERROR = "error"
|
||||
@@ -160,6 +160,12 @@ class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
|
||||
except:
|
||||
self.showtraceback()
|
||||
|
||||
def get_namespace(self):
|
||||
dbg_namespace = {}
|
||||
dbg_namespace.update(self.frame.f_globals)
|
||||
dbg_namespace.update(self.frame.f_locals) # locals later because it has precedence over the actual globals
|
||||
return dbg_namespace
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
# InteractiveConsoleCache
|
||||
@@ -175,6 +181,7 @@ class InteractiveConsoleCache:
|
||||
def get_interactive_console(thread_id, frame_id, frame, console_message):
|
||||
"""returns the global interactive console.
|
||||
interactive console should have been initialized by this time
|
||||
:rtype: DebugConsole
|
||||
"""
|
||||
if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id:
|
||||
return InteractiveConsoleCache.interactive_console_instance
|
||||
@@ -218,6 +225,16 @@ def execute_console_command(frame, thread_id, frame_id, line, buffer_output=True
|
||||
return console_message
|
||||
|
||||
|
||||
def get_description(frame, thread_id, frame_id, expression):
|
||||
console_message = ConsoleMessage()
|
||||
interpreter = get_interactive_console(thread_id, frame_id, frame, console_message)
|
||||
try:
|
||||
interpreter.frame = frame
|
||||
return interpreter.getDescription(expression)
|
||||
finally:
|
||||
interpreter.frame = None
|
||||
|
||||
|
||||
def get_completions(frame, act_tok):
|
||||
""" fetch all completions, create xml for the same
|
||||
return the completions xml
|
||||
|
||||
@@ -16,11 +16,10 @@ from _pydevd_bundle.pydevd_comm import CMD_RUN, CMD_VERSION, CMD_LIST_THREADS, C
|
||||
CMD_SET_PY_EXCEPTION, CMD_GET_FILE_CONTENTS, CMD_SET_PROPERTY_TRACE, CMD_ADD_EXCEPTION_BREAK, \
|
||||
CMD_REMOVE_EXCEPTION_BREAK, CMD_LOAD_SOURCE, CMD_ADD_DJANGO_EXCEPTION_BREAK, CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
|
||||
CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression, InternalConsoleGetCompletions, \
|
||||
CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE,\
|
||||
CMD_SHOW_RETURN_VALUES, ID_TO_MEANING
|
||||
CMD_RUN_CUSTOM_OPERATION, InternalRunCustomOperation, CMD_IGNORE_THROWN_EXCEPTION_AT, CMD_ENABLE_DONT_TRACE, \
|
||||
CMD_SHOW_RETURN_VALUES, ID_TO_MEANING, CMD_GET_DESCRIPTION, InternalGetDescription
|
||||
from _pydevd_bundle.pydevd_constants import get_thread_id, IS_PY3K, DebugInfoHolder, dict_contains, dict_keys, dict_pop, \
|
||||
STATE_RUN
|
||||
import pydevd_file_utils
|
||||
|
||||
|
||||
def process_net_command(py_db, cmd_id, seq, text):
|
||||
@@ -229,6 +228,14 @@ def process_net_command(py_db, cmd_id, seq, text):
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
elif cmd_id == CMD_GET_DESCRIPTION:
|
||||
try:
|
||||
|
||||
thread_id, frame_id, expression = text.split('\t', 2)
|
||||
int_cmd = InternalGetDescription(seq, thread_id, frame_id, expression)
|
||||
py_db.post_internal_command(int_cmd, thread_id)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
elif cmd_id == CMD_GET_FRAME:
|
||||
thread_id, frame_id, scope = text.split('\t', 2)
|
||||
|
||||
@@ -24,17 +24,22 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class PyResolveContext {
|
||||
private final boolean myAllowImplicits;
|
||||
private final boolean myAllowProperties;
|
||||
private final boolean myAllowRemote;
|
||||
private final TypeEvalContext myTypeEvalContext;
|
||||
|
||||
|
||||
private PyResolveContext(boolean allowImplicits, boolean allowProperties) {
|
||||
myAllowImplicits = allowImplicits;
|
||||
myAllowProperties = allowProperties;
|
||||
myTypeEvalContext = null;
|
||||
myAllowRemote = false;
|
||||
}
|
||||
|
||||
private PyResolveContext(boolean allowImplicits, boolean allowProperties, TypeEvalContext typeEvalContext) {
|
||||
|
||||
private PyResolveContext(boolean allowImplicits, boolean allowProperties, boolean allowRemote, TypeEvalContext typeEvalContext) {
|
||||
myAllowImplicits = allowImplicits;
|
||||
myAllowProperties = allowProperties;
|
||||
myAllowRemote = allowRemote;
|
||||
myTypeEvalContext = typeEvalContext;
|
||||
}
|
||||
|
||||
@@ -46,6 +51,10 @@ public class PyResolveContext {
|
||||
return myAllowProperties;
|
||||
}
|
||||
|
||||
public boolean allowRemote() {
|
||||
return myAllowRemote;
|
||||
}
|
||||
|
||||
private static final PyResolveContext ourDefaultContext = new PyResolveContext(true, true);
|
||||
private static final PyResolveContext ourNoImplicitsContext = new PyResolveContext(false, true);
|
||||
private static final PyResolveContext ourNoPropertiesContext = new PyResolveContext(false, false);
|
||||
@@ -63,11 +72,15 @@ public class PyResolveContext {
|
||||
}
|
||||
|
||||
public PyResolveContext withTypeEvalContext(@NotNull TypeEvalContext context) {
|
||||
return new PyResolveContext(myAllowImplicits, myAllowProperties, context);
|
||||
return new PyResolveContext(myAllowImplicits, myAllowProperties, myAllowRemote, context);
|
||||
}
|
||||
|
||||
public PyResolveContext withoutImplicits() {
|
||||
return new PyResolveContext(false, myAllowProperties, myTypeEvalContext);
|
||||
return new PyResolveContext(false, myAllowProperties, myAllowRemote, myTypeEvalContext);
|
||||
}
|
||||
|
||||
public PyResolveContext withRemote() {
|
||||
return new PyResolveContext(myAllowImplicits, myAllowProperties, true, myTypeEvalContext);
|
||||
}
|
||||
|
||||
public TypeEvalContext getTypeEvalContext() {
|
||||
|
||||
@@ -30,7 +30,9 @@ public abstract class AbstractCommand<T> {
|
||||
public static final int LOAD_SOURCE = 124;
|
||||
public static final int SMART_STEP_INTO = 128;
|
||||
public static final int EXIT = 129;
|
||||
|
||||
public static final int GET_DESCRIPTION = 148;
|
||||
|
||||
|
||||
public static final int CALL_SIGNATURE_TRACE = 130;
|
||||
|
||||
public static final int CMD_SET_PY_EXCEPTION = 131;
|
||||
@@ -52,6 +54,7 @@ public abstract class AbstractCommand<T> {
|
||||
public static final int SHOW_RETURN_VALUES = 146;
|
||||
public static final int INPUT_REQUESTED = 147;
|
||||
|
||||
|
||||
public static final int ERROR = 901;
|
||||
|
||||
public static final int VERSION = 501;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.jetbrains.python.debugger.pydev;
|
||||
|
||||
import com.jetbrains.python.debugger.PyDebugValue;
|
||||
import com.jetbrains.python.debugger.PyDebuggerException;
|
||||
|
||||
/**
|
||||
* @author traff
|
||||
*/
|
||||
public class GetDescriptionCommand extends AbstractFrameCommand {
|
||||
|
||||
private String myActionToken;
|
||||
private String result = null;
|
||||
|
||||
public GetDescriptionCommand(final RemoteDebugger debugger, String threadId, String frameId, final String myActionToken) {
|
||||
super(debugger, GET_DESCRIPTION, threadId, frameId);
|
||||
this.myActionToken = myActionToken;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isResponseExpected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse(ProtocolFrame response) throws PyDebuggerException {
|
||||
super.processResponse(response);
|
||||
try {
|
||||
PyDebugValue pyDebugValue = ProtocolParser.parseValue(response.getPayload(), getDebugger().getDebugProcess());
|
||||
result = pyDebugValue.getValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new PyDebuggerException("cant obtain completions", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void buildPayload(Payload payload) {
|
||||
super.buildPayload(payload);
|
||||
payload.add(myActionToken);
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -518,6 +518,11 @@ public class MultiProcessDebugger implements ProcessDebugger {
|
||||
return debugger(threadId).getCompletions(threadId, frameId, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String threadId, String frameId, String cmd) {
|
||||
return debugger(threadId).getDescription(threadId, frameId, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
|
||||
for (RemoteDebugger d : allDebuggers()) {
|
||||
|
||||
@@ -87,6 +87,9 @@ public interface ProcessDebugger {
|
||||
|
||||
List<PydevCompletionVariant> getCompletions(String threadId, String frameId, String prefix);
|
||||
|
||||
String getDescription(String threadId, String frameId, String cmd);
|
||||
|
||||
|
||||
void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
|
||||
|
||||
void removeExceptionBreakpoint(ExceptionBreakpointCommandFactory factory);
|
||||
|
||||
@@ -761,6 +761,13 @@ public class RemoteDebugger implements ProcessDebugger {
|
||||
return command.getCompletions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String threadId, String frameId, String cmd) {
|
||||
final GetDescriptionCommand command = new GetDescriptionCommand(this, threadId, frameId, cmd);
|
||||
execute(command);
|
||||
return command.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExceptionBreakpoint(ExceptionBreakpointCommandFactory factory) {
|
||||
execute(factory.createAddCommand(this));
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
|
||||
final PyCallExpression callExpr = argumentList.getCallExpression();
|
||||
if (callExpr != null) {
|
||||
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(argumentList.getProject(), argumentList.getContainingFile());
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(typeEvalContext);
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withRemote().withTypeEvalContext(typeEvalContext);
|
||||
final PyCallExpression.PyArgumentsMapping mapping = callExpr.mapArguments(resolveContext);
|
||||
if (mapping.getMarkedCallee() != null) {
|
||||
context.setItemsToShow(new Object[] { mapping });
|
||||
@@ -152,7 +152,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
|
||||
PyPsiUtils.assertValid(callExpression);
|
||||
// really we need to redo analysis every UI update; findElementForParameterInfo isn't called while typing
|
||||
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(callExpression.getProject(), callExpression.getContainingFile());
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(typeEvalContext);
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withRemote().withTypeEvalContext(typeEvalContext);
|
||||
final PyCallExpression.PyArgumentsMapping mapping = callExpression.mapArguments(resolveContext);
|
||||
final PyMarkedCallee marked = mapping.getMarkedCallee();
|
||||
if (marked == null) return; // resolution failed
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
package com.jetbrains.python.console;
|
||||
|
||||
import com.intellij.lang.documentation.AbstractDocumentationProvider;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.console.completion.PydevConsoleElement;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunication;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.console.completion.PydevConsoleReference;
|
||||
import com.jetbrains.python.documentation.PyDocumentationBuilder;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyReferenceExpression;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -49,21 +51,21 @@ public class PydevDocumentationProvider extends AbstractDocumentationProvider {
|
||||
|
||||
@Nullable
|
||||
public static String createDoc(final PsiElement element, final PsiElement originalElement) {
|
||||
final PyExpression expression = PsiTreeUtil.getParentOfType(originalElement, PyExpression.class);
|
||||
final PyReferenceExpression expression = PsiTreeUtil.getNonStrictParentOfType(originalElement, PyReferenceExpression.class);
|
||||
// Indicates that we are inside console, not a lookup element!
|
||||
if (expression == null){
|
||||
return null;
|
||||
}
|
||||
final ConsoleCommunication communication = PydevConsoleRunner.getConsoleCommunication(originalElement);
|
||||
if (communication == null){
|
||||
PydevConsoleReference consoleRef = PyUtil.as(expression.getReference(), PydevConsoleReference.class);
|
||||
if (consoleRef == null) { //shouldn't really happen!
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final String description = communication.getDescription(expression.getText());
|
||||
return StringUtil.isEmptyOrSpaces(description) ? null : description;
|
||||
}
|
||||
catch (Exception e) {
|
||||
PyElement documentationElement = consoleRef.getDocumentationElement();
|
||||
if (documentationElement == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new PyDocumentationBuilder(documentationElement, null).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(String text) {
|
||||
return null;
|
||||
public String getDescription(String refExpression) throws Exception {
|
||||
return myDebugProcess.getDescription(refExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.console.completion;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
@@ -24,19 +25,18 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiPolyVariantReferenceBase;
|
||||
import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.console.pydev.ConsoleCommunication;
|
||||
import com.jetbrains.python.console.pydev.IToken;
|
||||
import com.jetbrains.python.console.pydev.PyCodeCompletionImages;
|
||||
import com.jetbrains.python.console.pydev.PydevCompletionVariant;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyReferenceExpression;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -46,20 +46,75 @@ import java.util.Map;
|
||||
* @author oleg
|
||||
*/
|
||||
public class PydevConsoleReference extends PsiPolyVariantReferenceBase<PyReferenceExpression> {
|
||||
|
||||
private final ConsoleCommunication myCommunication;
|
||||
private final String myPrefix;
|
||||
private final boolean myAllowRemoteResolve;
|
||||
|
||||
public PydevConsoleReference(final PyReferenceExpression expression,
|
||||
final ConsoleCommunication communication,
|
||||
final String prefix) {
|
||||
final ConsoleCommunication communication, final String prefix, boolean allowRemoteResolve) {
|
||||
super(expression, true);
|
||||
myCommunication = communication;
|
||||
myPrefix = prefix;
|
||||
myAllowRemoteResolve = allowRemoteResolve;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ResolveResult[] multiResolve(boolean incompleteCode) {
|
||||
return ResolveResult.EMPTY_ARRAY;
|
||||
if (!myAllowRemoteResolve) {
|
||||
return RatedResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
PyExpression pyExpression = resolveFromStub();
|
||||
if (pyExpression == null) {
|
||||
return RatedResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
if (pyExpression instanceof PyReferenceExpression) {
|
||||
final PsiReference redirectedRef = pyExpression.getReference();
|
||||
if (redirectedRef != null) {
|
||||
PsiElement resolved = redirectedRef.resolve();
|
||||
if (resolved != null) {
|
||||
return new ResolveResult[]{new RatedResolveResult(RatedResolveResult.RATE_HIGH, resolved)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RatedResolveResult.EMPTY_ARRAY;
|
||||
|
||||
}
|
||||
|
||||
public PyElement getDocumentationElement() {
|
||||
return resolveFromStub();
|
||||
}
|
||||
|
||||
|
||||
private PyExpression resolveFromStub() {
|
||||
String qualifiedName = myElement.getText();
|
||||
if (qualifiedName == null) {
|
||||
return null;
|
||||
}
|
||||
String description;
|
||||
try {
|
||||
|
||||
description = myCommunication.getDescription(qualifiedName);
|
||||
if (Strings.isNullOrEmpty(description)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PyElementGenerator generator = PyElementGenerator.getInstance(myElement.getProject());
|
||||
PyFile dummyFile = (PyFile)generator.createDummyFile(LanguageLevel.forElement(myElement), description);
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(myElement);
|
||||
if (module != null) {
|
||||
dummyFile.putUserData(ModuleUtilCore.KEY_MODULE, module);
|
||||
}
|
||||
|
||||
List<PyStatement> statements = dummyFile.getStatements();
|
||||
PyStatement pyStatement = statements.get(statements.size() - 1);
|
||||
return pyStatement instanceof PyExpressionStatement ? ((PyExpressionStatement)pyStatement).getExpression() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -71,8 +126,7 @@ public class PydevConsoleReference extends PsiPolyVariantReferenceBase<PyReferen
|
||||
final PsiManager manager = myElement.getManager();
|
||||
final String name = completion.getName();
|
||||
final int type = completion.getType();
|
||||
LookupElementBuilder builder = LookupElementBuilder
|
||||
.create(new PydevConsoleElement(manager, name, completion.getDescription()))
|
||||
LookupElementBuilder builder = LookupElementBuilder.create(new PydevConsoleElement(manager, name, completion.getDescription()))
|
||||
.withIcon(PyCodeCompletionImages.getImageForType(type));
|
||||
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@ public class PyConsoleParser extends PyParser{
|
||||
private PythonConsoleData myPythonConsoleData;
|
||||
private boolean myIPythonStartSymbol;
|
||||
|
||||
public PyConsoleParser(PythonConsoleData pythonConsoleData) {
|
||||
public PyConsoleParser(PythonConsoleData pythonConsoleData, LanguageLevel languageLevel) {
|
||||
myPythonConsoleData = pythonConsoleData;
|
||||
myLanguageLevel = LanguageLevel.getDefault();
|
||||
myLanguageLevel = languageLevel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -901,6 +901,17 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription(String prefix) throws Exception {
|
||||
if (isConnected()) {
|
||||
dropFrameCaches();
|
||||
final PyStackFrame frame = currentFrame();
|
||||
return myDebugger.getDescription(frame.getThreadId(), frame.getFrameId(), prefix);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startNotified(ProcessEvent event) {
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class PyFileElementType extends IStubFileElementType<PyFileStub> {
|
||||
final Project project = psi.getProject();
|
||||
final PsiBuilderFactory factory = PsiBuilderFactory.getInstance();
|
||||
final PsiBuilder builder = factory.createBuilder(project, node, lexer, getLanguage(), node.getChars());
|
||||
final PyParser parser = new PyConsoleParser(consoleData);
|
||||
final PyParser parser = new PyConsoleParser(consoleData, getLanguageLevel(psi));
|
||||
|
||||
return parser.parse(this, builder).getFirstChildNode();
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
|
||||
final ConsoleCommunication communication = file.getCopyableUserData(PydevConsoleRunner.CONSOLE_KEY);
|
||||
if (communication != null) {
|
||||
if (qualifier != null) {
|
||||
return new PydevConsoleReference(this, communication, qualifier.getText() + ".");
|
||||
return new PydevConsoleReference(this, communication, qualifier.getText() + ".", context.allowRemote());
|
||||
}
|
||||
return new PydevConsoleReference(this, communication, "");
|
||||
return new PydevConsoleReference(this, communication, "", context.allowRemote());
|
||||
}
|
||||
|
||||
if (qualifier != null) {
|
||||
|
||||
Reference in New Issue
Block a user