Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2012-07-26 20:10:45 +04:00
20 changed files with 1096 additions and 93 deletions
@@ -136,6 +136,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
rtype = getReturnTypeByQName(overloadedQName, anchor);
if (rtype != null) {
boolean matched = true;
boolean notNullParameterMatch = false;
for (Map.Entry<PyExpression, PyNamedParameter> entry : arguments.entrySet()) {
final PyNamedParameter p = entry.getValue();
final String name = p.getName();
@@ -144,7 +145,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
PyType argType = entry.getKey().getType(context);
// Special case for the 'mode' argument of the 'open()' builtin
if (("__builtin__.open".equals(qname) || "io.open".equals(qname)) && "mode".equals(name)) {
if (("__builtin__.open".equals(qname) || "io.open".equals(qname) || "os.fdopen".equals(qname)) && "mode".equals(name)) {
final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor);
final LanguageLevel level = LanguageLevel.forElement(anchor);
argType = cache.getUnicodeType(level);
@@ -157,11 +158,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
}
final PyType paramType = getParameterTypeByQName(overloadedQName, name, anchor);
if (!PyTypeChecker.match(paramType, argType, context)) {
if (PyTypeChecker.match(paramType, argType, context)) {
if (argType != null && paramType != null) {
notNullParameterMatch = true;
}
}
else {
matched = false;
}
}
if (matched) {
if (matched && notNullParameterMatch) {
return rtype;
}
}
@@ -1822,6 +1822,934 @@ decimal.Decimal.__neg__ = \
:rtype: decimal.Decimal \n\
# 10.1. os.path
os.path.abspath = \
:type path: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.abspath.1 = \
:type path: bytes \n\
:rtype: bytes \n\
os.path.abspath.2 = \
:type path: unicode \n\
:rtype: unicode \n\
os.path.basename = \
:type p: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.basename.1 = \
:type p: bytes \n\
:rtype: bytes \n\
os.path.basename.2 = \
:type p: unicode \n\
:rtype: unicode \n\
os.path.commonprefix = \
:type m: collections.Iterable of string \n\
:rtype: bytes or unicode \n\
os.path.commonprefix.1 = \
:type m: collections.Iterable of bytes \n\
:rtype: bytes \n\
os.path.commonprefix.2 = \
:type m: collections.Iterable of unicode \n\
:rtype: unicode \n\
os.path.dirname = \
:type p: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.dirname.1 = \
:type p: bytes \n\
:rtype: bytes \n\
os.path.dirname.2 = \
:type p: unicode \n\
:rtype: unicode \n\
os.path.exists = \
:type path: bytes or unicode \n\
:rtype: bool \n\
os.path.lexists = \
:type path: bytes or unicode \n\
:rtype: bool \n\
os.path.expanduser = \
:type path: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.expanduser.1 = \
:type path: bytes \n\
:rtype: bytes \n\
os.path.expanduser.2 = \
:type path: unicode \n\
:rtype: unicode \n\
os.path.expandvars = \
:type path: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.expandvars.1 = \
:type path: bytes \n\
:rtype: bytes \n\
os.path.expandvars.2 = \
:type path: unicode \n\
:rtype: unicode \n\
os.path.getatime = \
:type filename: bytes or unicode \n\
:rtype: int or float \n\
os.path.getmtime = \
:type filename: bytes or unicode \n\
:rtype: int or float \n\
os.path.getctime = \
:type filename: bytes or unicode \n\
:rtype: int or float \n\
os.path.getsize = \
:type filename: bytes or unicode \n\
:rtype: int or long \n\
os.path.isabs = \
:type s: bytes or unicode \n\
:rtype: bool \n\
os.path.isfile = \
:type path: bytes or unicode \n\
:rtype: bool \n\
os.path.isdir = \
:type s: bytes or unicode \n\
:rtype: bool \n\
os.path.islink = \
:type path: bytes or unicode \n\
:rtype: bool \n\
os.path.ismount = \
:type path: bytes or unicode \n\
:rtype: bool \n\
os.path.join = \
:type a: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.join.1 = \
:type a: bytes \n\
:rtype: bytes \n\
os.path.join.2 = \
:type a: unicode \n\
:rtype: unicode \n\
os.path.normcase = \
:type s: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.normcase.1 = \
:type s: bytes \n\
:rtype: bytes \n\
os.path.normcase.2 = \
:type s: unicode \n\
:rtype: unicode \n\
os.path.normpath = \
:type path: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.normpath.1 = \
:type path: bytes \n\
:rtype: bytes \n\
os.path.normpath.2 = \
:type path: unicode \n\
:rtype: unicode \n\
os.path.realpath = \
:type filename: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.realpath.1 = \
:type filename: bytes \n\
:rtype: bytes \n\
os.path.realpath.2 = \
:type filename: unicode \n\
:rtype: unicode \n\
os.path.relpath = \
:type path: bytes or unicode \n\
:type start: bytes or unicode \n\
:rtype: bytes or unicode \n\
os.path.relpath.1 = \
:type path: bytes \n\
:rtype: bytes \n\
os.path.relpath.2 = \
:type path: unicode \n\
:rtype: unicode \n\
os.path.samefile = \
:type f1: bytes or unicode \n\
:type f2: bytes or unicode \n\
:rtype: bool \n\
os.path.sameopenfile = \
:type fp1: int \n\
:type fp2: int \n\
:rtype: bool \n\
os.path.samestat = \
:type s1: os.stat_result or tuple \n\
:type s2: os.stat_result or tuple \n\
:rtype: bool \n\
os.path.split = \
:type p: bytes or unicode \n\
:rtype: (bytes or unicode, bytes or unicode) \n\
os.path.split.1 = \
:type p: bytes \n\
:rtype: (bytes, bytes) \n\
os.path.split.2 = \
:type p: unicode \n\
:rtype: (unicode, unicode) \n\
os.path.splitdrive = \
:type p: bytes or unicode \n\
:rtype: (bytes or unicode, bytes or unicode) \n\
os.path.splitdrive.1 = \
:type p: bytes \n\
:rtype: (bytes, bytes) \n\
os.path.splitdrive.2 = \
:type p: unicode \n\
:rtype: (unicode, unicode) \n\
os.path.splitext = \
:type p: bytes or unicode \n\
:rtype: (bytes or unicode, bytes or unicode) \n\
os.path.splitext.1 = \
:type p: bytes \n\
:rtype: (bytes, bytes) \n\
os.path.splitext.2 = \
:type p: unicode \n\
:rtype: (unicode, unicode) \n\
os.path.splitunc = \
:type p: bytes or unicode \n\
:rtype: (bytes or unicode, bytes or unicode) \n\
os.path.splitunc.1 = \
:type p: bytes \n\
:rtype: (bytes, bytes) \n\
os.path.splitunc.2 = \
:type p: unicode \n\
:rtype: (unicode, unicode) \n\
os.path.walk = \
:type top: bytes or unicode \n\
:rtype: None \n\
## 10.10. shutil
shutil.copyfile = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.copymode = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.copystat = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.copy = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.copy2 = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.copytree = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:type symlinks: bool \n\
:type ignore: collections.Callable or None \n\
:rtype None \n\
shutil.rmtree = \
:type path: bytes or unicode \n\
:type ignore_errors: bool\n\
:type onerror: collections.Callable or None \n\
:rtype None \n\
shutil.move = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype None \n\
shutil.make_archive = \
:type base_name: bytes or unicode \n\
:type format: bytes or unicode \n\
:type root_dir: bytes or unicode or None \n\
:type base_dir: bytes or unicode or None \n\
:type verbose: bool or int \n\
:type dry_run: bool or int \n\
:type owner: bytes or unicode or int or None \n\
:type group: bytes or unicode or int or None \n\
:rtype: bytes or unicode \n\
shutil.get_archive_formats = \
:rtype: list of (string, string) \n\
shutil.register_archive_format = \
:type name: bytes or unicode \n\
:type function: collections.Callable \n\
:type extra_args: None or collections.Sequence of (string, object) \n\
:type description: bytes or unicode \n\
:rtype: None
shutil.unregister_archive_format = \
:type name: bytes or unicode \n\
:rtype: None \n\
## 15.1. os
os.ctermid = \
:rtype: unicode \n\
os.getegid = \
:rtype: int \n\
os.geteuid = \
:rtype: int \n\
os.getgid = \
:rtype: int \n\
os.getgroups = \
:rtype: list of int \n\
os.initgroups = \
:type username: string \n\
:type gid: int \n\
:rtype: None \n\
os.getlogin = \
:rtype: unicode \n\
os.getpgid = \
:type pid: int \n\
:rtype: int \n\
os.getpgrp = \
:rtype: int \n\
os.getpid = \
:rtype: int \n\
os.getresuid = \
:rtype: (int, int, int) \n\
os.getuid = \
:rtype: int \n\
os.getenv = \
:type key: string \n\
:type default: object \n\
:rtype: string \n\
os.putenv = \
:type key: bytes or unicode \n\
:type value: bytes or unicode \n\
:rtype: None \n\
os.setegid = \
:type gid: int \n\
:rtype: None \n\
os.seteuid = \
:type uid: int \n\
:rtype: None \n\
os.setgid = \
:type gid: int \n\
:rtype: None \n\
os.setgroups = \
:type p_list: list of int \n\
:rtype: None \n\
os.setpgrp = \
:rtype: None \n\
os.setpgid = \
:type pid: int \n\
:type pgrp: int \n\
:rtype: None \n\
os.setregid = \
:type rgid: int \n\
:type egid: int \n\
:rtype: None \n\
os.setresgid = \
:type rgid: int \n\
:type egid: int \n\
:type sgid: int \n\
:rtype: None \n\
os.setresuid = \
:type ruid: int \n\
:type euid: int \n\
:type suid: int \n\
:rtype: None \n\
os.setreuid = \
:type ruid: int \n\
:type euid: int \n\
:rtype: None \n\
os.getsid = \
:type pid: int \n\
:rtype: int \n\
os.setsid = \
:rtype: None \n\
os.setuid = \
:type uid: int \n\
:rtype: None \n\
os.strerror = \
:type code: int \n\
:rtype: unicode \n\
os.umask = \
:type new_mask: int \n\
:rtype: int \n\
os.uname = \
:rtype: (unicode, unicode, unicode, unicode, unicode) \n\
os.unsetenv = \
:type key: string \n\
:rtype: None \n\
os.fdopen = \
:type fd: int \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: file \n\
os.fdopen.1 = \
:type mode: unicode \n\
:rtype: io.TextIOWrapper \n\
os.fdopen.2 = \
:type mode: bytes \n\
:rtype: io.FileIO \n\
os.popen = \
:type command: string \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: io.FileIO \n\
os.tmpfile = \
:rtype: io.FileIO \n\
os.popen2 = \
:type cmd: string \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: (io.FileIO, io.FileIO) \n\
os.popen3 = \
:type cmd: string \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: (io.FileIO, io.FileIO, io.FileIO) \n\
os.popen4 = \
:type cmd: string \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: (io.FileIO, io.FileIO) \n\
os.close = \
:type fd: int \n\
:rtype: None \n\
os.closerange = \
:type fd_low: int \n\
:type fd_high: int \n\
:rtype: None \n\
os.dup = \
:type fd: int \n\
:rtype: int \n\
os.dup2 = \
:type old_fd: int \n\
:type new_fd: int \n\
:rtype: None \n\
os.fchmod = \
:type fd: int \n\
:type mode: int \n\
:rtype: None \n\
os.fchown = \
:type fd: int \n\
:type uid: int \n\
:type gid: int \n\
:rtype: None \n\
os.fdatasync = \
:type fildes: int \n\
:rtype: None \n\
os.fpathconf = \
:type fd: int \n\
:type name: int or string \n\
os.fstat = \
:type fd: int \n\
:rtype: os.stat_result \n\
os.fstatvfs = \
:type fd: int \n\
:rtype: os.statvfs_result \n\
os.fsync = \
:type filedes: int \n\
:rtype: None \n\
os.ftruncate = \
:type fd: int \n\
:type length: int or long \n\
:rtype: None \n\
os.isatty = \
:type fd: int \n\
:rtype: bool \n\
os.lseek = \
:type fd: int \n\
:type pos: int or long \n\
:type how: int \n\
:rtype: None \n\
os.open = \
:type filename: string \n\
:type mode: string \n\
:type bufsize: int \n\
:rtype: int \n\
os.openpty = \
:rtype: (int, int) \n\
os.pipe = \
:rtype: (int, int) \n\
os.read = \
:type fd: int \b\
:type buffersize: int or long \n\
:rtype: bytes \n\
os.tcgetpgrp = \
:type fd: int \n\
:rtype: int \n\
os.tcsetpgrp = \
:type fd: int \n\
:type pgid: int \n\
:rtype: None \n\
os.ttyname = \
:type fd: int \n\
:rtype: unicode \n\
os.write = \
:type fd: int \n\
:type string: bytes \n\
:rtype: int \n\
os.access = \
:type path: bytes or unicode \n\
:type mode: int \n\
:rtype: bool \n\
os.chdir = \
:type path: bytes or unicode \n\
:rtype: None \n\
os.fchdir = \
:type filedes: int \n\
:rtype: None \n\
os.getcwd = \
:rtype: bytes \n\
os.getcwdu = \
:rtype: unicode \n\
os.chroot = \
:type path: bytes or unicode \n\
:rtype: None \n\
os.chmod = \
:type path: bytes or unicode \n\
:type mode: int \n\
:rtype: None \n\
os.chown = \
:type path: bytes or unicode \n\
:type uid: int \n\
:type gid: int \n\
:rtype: None \n\
os.lchown = \
:type path: bytes or unicode \n\
:type uid: int \n\
:type gid: int \n\
:rtype: None \n\
os.link = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype: None \n\
os.listdir = \
:type path: bytes or unicode \n\
:rtype: list of string \n\
os.listdir.1 = \
:type path: unicode \n\
:rtype: list of unicode \n\
os.lstat = \
:type path: bytes or unicode \n\
:rtype: os.stat_result \n\
os.mkfifo = \
:type filename: bytes or unicode \n\
:type mode: int \n\
:rtype: None \n\
os.mknod = \
:type filename: bytes or unicode \n\
:type mode: int \n\
:type device: int \n\
:rtype: None \n\
os.major = \
:type device: int \n\
:rtype: int \n\
os.minor = \
:type device: int \n\
:rtype: int \n\
os.makedev = \
:type major: int \n\
:type minor: int \n\
:rtype: int \n\
os.mkdir = \
:type path: bytes or unicode \n\
:type mode: int \n\
:rtype: None \n\
os.makedirs = \
:type name: bytes or unicode \n\
:type mode: int \n\
:rtype: None \n\
os.pathconf = \
:type path: bytes or unicode \n\
:type name: int or string \n\
os.readlink = \
:type path: bytes or unicode \n\
:rtype: string \n\
os.readlink.1 = \
:type path: unicode \n\
:rtype: unicode \n\
os.remove = \
:type path: bytes or unicode \n\
:rtype: None \n\
os.removedirs = \
:type name: bytes or unicode \n\
:rtype: None \n\
os.rename = \
:type old: bytes or unicode \n\
:type new: bytes or unicode \n\
:rtype: None \n\
os.renames = \
:type old: bytes or unicode \n\
:type new: bytes or unicode \n\
:rtype: None \n\
os.rmdir = \
:type path: bytes or unicode \n\
:rtype: None \n\
os.stat = \
:type path: bytes or unicode \n\
:rtype: os.stat_result \n\
os.stat_float_times = \
:type newval: bool or None \n\
:rtype: bool \n\
os.statvfs = \
:type path: bytes or unicode \n\
:rtype: os.statvfs_result \n\
os.symlink = \
:type src: bytes or unicode \n\
:type dst: bytes or unicode \n\
:rtype: None \n\
os.tempnam = \
:type dir: bytes or unicode \n\
:type prefix: bytes or unicode \n\
:rtype: string \n\
os.tmpnam = \
:rtype: string \n\
os.unlink = \
:type path: bytes or unicode \n\
:rtype: None \n\
os.utime = \
:type path: bytes or unicode \n\
:type atime: int or float \n\
:type mtime: int or float \n\
:rtype: None \n\
os.walk = \
:type top: bytes or unicode \n\
:type topdown: bool \n\
:type followlinks: bool \n\
:rtype: collections.Iterable of (string, list of string, list of string) \n\
os.walk.1 = \
:type top: bytes \n\
:type topdown: bool \n\
:type followlinks: bool \n\
:rtype: collections.Iterable of (bytes, list of bytes, list of bytes) \n\
os.walk.2 = \
:type top: unicode \n\
:type topdown: bool \n\
:type followlinks: bool \n\
:rtype: collections.Iterable of (unicode, list of unicode, list of unicode) \n\
os.execl = \
:type file: bytes or unicode \n\
:rtype: None \n\
os.execle = \
:type file: bytes or unicode \n\
:rtype: None \n\
os.execlp = \
:type file: bytes or unicode \n\
:rtype: None \n\
os.execlpe = \
:type file: bytes or unicode \n\
:rtype: None \n\
os.execv = \
:type path: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:rtype: None \n\
os.execve = \
:type path: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:type env: collections.Mapping of (string, string) \n\
:rtype: None \n\
os.execvp = \
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:rtype: None \n\
os.execvpe = \
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:type env: collections.Mapping of (string, string) \n\
:rtype: None \n\
os._exit = \
:type status: int \n\
:rtype: None \n\
os.fork = \
:rtype: int \n\
os.forkpty = \
:rtype: (int, int) \n\
os.kill = \
:type pid: int \n\
:type sig: int \n\
:rtype: None \n\
os.killpg = \
:type pgid: int \n\
:type sig: int \n\
:rtype: None \n\
os.nice = \
:type inc: int \n\
:rtype: int \n\
os.spawnl = \
:type mode: int \n\
:type file: bytes or unicode \n\
:rtype: int \n\
os.spawnle = \
:type mode: int \n\
:type file: bytes or unicode \n\
:rtype: int \n\
os.spawnlp = \
:type mode: int \n\
:type file: bytes or unicode \n\
:rtype: int \n\
os.spawnlpe = \
:type mode: int \n\
:type file: bytes or unicode \n\
:rtype: int \n\
os.spawnv = \
:type mode: int \n\
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:rtype: int \n\
os.spawnve = \
:type mode: int \n\
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:type env: collections.Mapping of (string, string) \n\
:rtype: int \n\
os.spawnvp = \
:type mode: int \n\
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:rtype: int \n\
os.spawnvpe = \
:type mode: int \n\
:type file: bytes or unicode \n\
:type args: collections.Iterable of string \n\
:type env: collections.Mapping of (string, string) \n\
:rtype: int \n\
os.system = \
:type command: bytes or unicode \n\
:rtype: int \n\
os.times = \
:rtype: (float, float, float, float, float) \n\
os.wait = \
:rtype: (int, int) \n\
os.waitpid = \
:type pid: int \n\
:type options: int \n\
:rtype: (int, int) \n\
os.wait3 = \
:type options: int \n\
:rtype: (int, int, resource.struct_rusage) \n\
os.wait4 = \
:type pid: int \n\
:type options: int \n\
:rtype: (int, int, resource.struct_rusage) \n\
os.WCOREDUMP = \
:type status: int \n\
:rtype: bool \n\
os.WIFCONTINUED = \
:type status: int \n\
:rtype: bool \n\
os.WIFSTOPPED = \
:type status: int \n\
:rtype: bool \n\
os.WIFSIGNALED = \
:type status: int \n\
:rtype: bool \n\
os.WIFEXITED = \
:type status: int \n\
:rtype: bool \n\
os.WEXITSTATUS = \
:type status: int \n\
:rtype: bool \n\
os.WSTOPSIG = \
:type status: int \n\
:rtype: bool \n\
os.WTERMSIG = \
:type status: int \n\
:rtype: bool \n\
os.urandom = \
:type n: int \n\
:rtype: bytes \n\
## 15.2. io
io.open = \
@@ -1948,6 +2876,13 @@ base64.b64decode = \
:rtype: bytes \n\
## 27.1. sys
sys.exit = \
:type status: int \n\
:rtype: None \n\
# 27.13. inspect
# Fake <type 'generator'>
@@ -370,6 +370,12 @@ __builtin__.range.__init__ = \
:rtype: range of int \n\
## 15.1. os
os.getcwd = \
:rtype: str \n\
## 15.2. io
io.IOBase.readlines = \
@@ -88,7 +88,7 @@ class DocumentationBuilder {
if (property != null) {
is_property = true;
final AccessDirection dir = AccessDirection.of((PyElement)outer);
Maybe<PyFunction> accessor = property.getByDirection(dir);
Maybe<Callable> accessor = property.getByDirection(dir);
myProlog
.addItem("property ").addWith(TagBold, $().addWith(TagCode, $(element_name)))
.addItem(" of ").add(PythonDocumentationProvider.describeClass(cls, TagCode, true, true))
@@ -97,10 +97,10 @@ class DocumentationBuilder {
myBody.addItem(": ").addItem(property.getDoc()).addItem(BR);
}
else {
final PyFunction getter = property.getGetter().valueOrNull();
if (getter != null && getter != myElement) {
final Callable getter = property.getGetter().valueOrNull();
if (getter != null && getter != myElement && getter instanceof PyFunction) {
// not in getter, getter's doc comment may be useful
PyStringLiteralExpression docstring = getter.getDocStringExpression();
PyStringLiteralExpression docstring = ((PyFunction)getter).getDocStringExpression();
if (docstring != null) {
myProlog
.addItem(BR).addWith(TagItalic, $("Copied from getter:")).addItem(BR)
@@ -90,7 +90,7 @@ public class PyPropertyAccessInspection extends PyInspection {
}
private void checkAccessor(PyExpression node, String name, AccessDirection dir, Property property) {
final Maybe<PyFunction> accessor = property.getByDirection(dir);
final Maybe<Callable> accessor = property.getByDirection(dir);
if (accessor.isDefined() && accessor.value() == null) {
final String message;
if (dir == AccessDirection.WRITE) {
@@ -119,8 +119,10 @@ public class PyPropertyDefinitionInspection extends PyInspection {
else {
// @property; we only check getter, others are checked by visitPyFunction
// getter is always present with this form
final PyFunction function = property.getGetter().valueOrNull();
checkGetter(function, getFunctionMarkingElement(function));
final Callable callable = property.getGetter().valueOrNull();
if (callable instanceof PyFunction) {
checkGetter(callable, getFunctionMarkingElement((PyFunction)callable));
}
}
return false; // always want more
}
@@ -278,7 +280,7 @@ public class PyPropertyDefinitionInspection extends PyInspection {
(element instanceof PyYieldExpression);
}
});
hasReturns = returnStatements.length > 0;
hasReturns = returnStatements.length > 0;
}
else {
PyReferenceExpression callSite = being_checked instanceof PyReferenceExpression ? (PyReferenceExpression) being_checked : null;
@@ -18,19 +18,19 @@ public interface Property {
* @return the setter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<PyFunction> getSetter();
Maybe<Callable> getSetter();
/**
* @return the getter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<PyFunction> getGetter();
Maybe<Callable> getGetter();
/**
* @return the deleter: a method or null if defined, or something else callable if undefined.
*/
@NotNull
Maybe<PyFunction> getDeleter();
Maybe<Callable> getDeleter();
/**
* @return doc string as known to property() call. If null, see getter's doc.
@@ -39,7 +39,7 @@ public interface Property {
String getDoc();
/**
* @return the target to which the result of property() call is assigned. For things defined via @property, it is null.
* @return the target to which the result of property() call is assigned. For things defined via @property, it is null.
*/
@Nullable
PyTargetExpression getDefinitionSite();
@@ -49,6 +49,6 @@ public interface Property {
* @return getter, setter, or deleter.
*/
@NotNull
Maybe<PyFunction> getByDirection(@NotNull AccessDirection direction);
Maybe<Callable> getByDirection(@NotNull AccessDirection direction);
}
@@ -49,8 +49,8 @@ public abstract class PropertyBunch<MType> {
* @param ref a reference as an argument in property() call
* @return value we want to store (resolved callable, name, etc)
*/
protected abstract @Nullable MType translate(@NotNull PyReferenceExpression ref);
@Nullable
protected abstract MType translate(@NotNull PyExpression ref);
@Nullable
public static PyCallExpression findPropertyCallSite(@Nullable PyExpression source) {
@@ -140,10 +140,6 @@ public abstract class PropertyBunch<MType> {
}
private static <MType> Maybe<MType> translateIfSet(PropertyBunch<MType> target, PyExpression accessor) {
// TODO[yole] I don't quite understand this subtle distinction (why an accessor defined with lambda must be treated as defined=false)
if (accessor != null && !(accessor instanceof PyReferenceExpression)) {
return new Maybe<MType>();
}
return new Maybe<MType>(accessor == null ? null : target.translate((PyReferenceExpression) accessor));
return new Maybe<MType>(accessor == null ? null : target.translate(accessor));
}
}
@@ -5,10 +5,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.ResolveState;
import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
@@ -42,6 +39,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
import static com.jetbrains.python.psi.stubs.PyTargetExpressionStub.InitializerType.CallExpression;
/**
* @author yole
*/
@@ -492,8 +491,8 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return proc.getResult();
}
private final static Maybe<PyFunction> UNKNOWN_CALL = new Maybe<PyFunction>(); // denotes _not_ a PyFunction, actually
private final static Maybe<PyFunction> NONE = new Maybe<PyFunction>(null); // denotes an explicit None
private final static Maybe<Callable> UNKNOWN_CALL = new Maybe<Callable>(); // denotes _not_ a PyFunction, actually
private final static Maybe<Callable> NONE = new Maybe<Callable>(null); // denotes an explicit None
/**
* @param name name of the property
@@ -541,9 +540,9 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
}
}
for (Map.Entry<String, List<PyFunction>> entry: grouped.entrySet()) {
Maybe<PyFunction> getter = NONE;
Maybe<PyFunction> setter = NONE;
Maybe<PyFunction> deleter = NONE;
Maybe<Callable> getter = NONE;
Maybe<Callable> setter = NONE;
Maybe<Callable> deleter = NONE;
String doc = null;
final String decoratorName = entry.getKey();
for (PyFunction method : entry.getValue()) {
@@ -553,13 +552,13 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
final PyQualifiedName qname = deco.getQualifiedName();
if (qname != null) {
if (qname.matches(PyNames.PROPERTY)) {
getter = new Maybe<PyFunction>(method);
getter = new Maybe<Callable>(method);
}
else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.SETTER)) {
setter = new Maybe<PyFunction>(method);
setter = new Maybe<Callable>(method);
}
else if (useAdvancedSyntax && qname.matches(decoratorName, PyNames.DELETER)) {
deleter = new Maybe<PyFunction>(method);
deleter = new Maybe<Callable>(method);
}
}
}
@@ -574,14 +573,14 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return null;
}
private Maybe<PyFunction> fromPacked(Maybe<String> maybeName) {
private Maybe<Callable> fromPacked(Maybe<String> maybeName) {
if (maybeName.isDefined()) {
final String value = maybeName.value();
if (value == null || PyNames.NONE.equals(value)) {
return NONE;
}
PyFunction method = findMethodByName(value, true);
if (method != null) return new Maybe<PyFunction>(method);
if (method != null) return new Maybe<Callable>(method);
}
return UNKNOWN_CALL;
}
@@ -595,15 +594,23 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
final PyTargetExpressionStub targetStub = (PyTargetExpressionStub)substub;
PropertyStubStorage prop = targetStub.getCustomStub(PropertyStubStorage.class);
if (prop != null && (name == null || name.equals(targetStub.getName()))) {
Maybe<PyFunction> getter = fromPacked(prop.getGetter());
Maybe<PyFunction> setter = fromPacked(prop.getSetter());
Maybe<PyFunction> deleter = fromPacked(prop.getDeleter());
Maybe<Callable> getter = fromPacked(prop.getGetter());
Maybe<Callable> setter = fromPacked(prop.getSetter());
Maybe<Callable> deleter = fromPacked(prop.getDeleter());
String doc = prop.getDoc();
if (getter != NONE || setter != NONE || deleter != NONE) {
final PropertyImpl property = new PropertyImpl(targetStub.getName(), getter, setter, deleter, doc, targetStub.getPsi());
if (propertyProcessor == null || propertyProcessor.process(property)) return property;
}
}
final PyQualifiedName initializer = targetStub.getInitializer();
if (targetStub.getInitializerType() == CallExpression && initializer != null && PyNames.PROPERTY.equals(initializer.toString())) {
final PropertyImpl property = new PropertyImpl(targetStub.getName(), UNKNOWN_CALL, UNKNOWN_CALL, UNKNOWN_CALL,
null, targetStub.getPsi());
if (propertyProcessor == null || propertyProcessor.process(property)) {
return property;
}
}
}
}
}
@@ -702,10 +709,10 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return null;
}
private static class PropertyImpl extends PropertyBunch<PyFunction> implements Property {
private static class PropertyImpl extends PropertyBunch<Callable> implements Property {
private final String myName;
private PropertyImpl(String name, Maybe<PyFunction> getter, Maybe<PyFunction> setter, Maybe<PyFunction> deleter, String doc, PyTargetExpression site) {
private PropertyImpl(String name, Maybe<Callable> getter, Maybe<Callable> setter, Maybe<Callable> deleter, String doc, PyTargetExpression site) {
myName = name;
myDeleter = deleter;
myGetter = getter;
@@ -724,7 +731,7 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
@NotNull
@Override
public Maybe<PyFunction> getByDirection(@NotNull AccessDirection direction) {
public Maybe<Callable> getByDirection(@NotNull AccessDirection direction) {
switch (direction) {
case READ: return myGetter;
case WRITE: return mySetter;
@@ -733,12 +740,19 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
throw new IllegalArgumentException("Unknown direction " + PyUtil.nvl(direction));
}
@Nullable
@Override
protected PyFunction translate(@NotNull PyReferenceExpression ref) {
if (PyNames.NONE.equals(ref.getName())) return null; // short-circuit a common case
PsiElement something = ref.getReference().resolve();
if (something instanceof PyFunction) {
return (PyFunction)something;
protected Callable translate(@NotNull PyExpression expr) {
if (PyNames.NONE.equals(expr.getName())) return null; // short-circuit a common case
if (expr instanceof Callable) {
return (Callable)expr;
}
final PsiReference ref = expr.getReference();
if (ref != null) {
PsiElement something = ref.resolve();
if (something instanceof Callable) {
return (Callable)something;
}
}
return null;
}
@@ -2,11 +2,10 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyDecoratorList;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.stubs.PyDecoratorListStub;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.PyDecoratorList;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.stubs.PyDecoratorListStub;
import org.jetbrains.annotations.NotNull;
/**
@@ -38,8 +37,8 @@ public class PyDecoratorListImpl extends PyBaseElementImpl<PyDecoratorListStub>
public PyDecorator findDecorator(String name) {
final PyDecorator[] decorators = getDecorators();
for (PyDecorator decorator : decorators) {
final PyExpression callee = decorator.getCallee();
if (callee != null && name.equals(callee.getText())) {
final PyQualifiedName qName = decorator.getQualifiedName();
if (qName != null && name.equals(qName.toString())) {
return decorator;
}
}
@@ -19,7 +19,9 @@ import com.jetbrains.python.console.PydevConsoleRunner;
import com.jetbrains.python.console.completion.PydevConsoleReference;
import com.jetbrains.python.console.pydev.ConsoleCommunication;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.references.*;
import com.jetbrains.python.psi.impl.references.PyImportReference;
import com.jetbrains.python.psi.impl.references.PyQualifiedReference;
import com.jetbrains.python.psi.impl.references.PyReferenceImpl;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.refactoring.PyDefUseUtil;
@@ -218,24 +220,39 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
@Nullable
public Ref<PyType> getTypeOfProperty(@NotNull TypeEvalContext context) {
PyExpression qualifier = getQualifier();
final PyExpression qualifier = getQualifier();
final String name = getName();
if (name != null && qualifier != null) {
PyType qualifierType = context.getType(qualifier);
if (qualifierType instanceof PyClassType) {
final PyClassType classType = (PyClassType)qualifierType;
PyClass pyClass = classType.getPyClass();
if (pyClass != null) {
Property property = pyClass.findProperty(name);
if (property != null) {
if (classType.isDefinition()) {
return Ref.<PyType>create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY));
}
final Maybe<PyFunction> accessor = property.getByDirection(AccessDirection.of(this));
final PyFunction function = accessor.valueOrNull();
final PyType type = (function != null) ? function.getReturnType(context, this) : null;
return Ref.create(type);
final PyType qualifierType = context.getType(qualifier);
return getTypeOfProperty(qualifierType, name, context);
}
return null;
}
@Nullable
private Ref<PyType> getTypeOfProperty(@Nullable PyType qualifierType, @NotNull String name, @NotNull TypeEvalContext context) {
if (qualifierType instanceof PyClassType) {
final PyClassType classType = (PyClassType)qualifierType;
PyClass pyClass = classType.getPyClass();
if (pyClass != null) {
Property property = pyClass.findProperty(name);
if (property != null) {
if (classType.isDefinition()) {
return Ref.<PyType>create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY));
}
final Maybe<Callable> accessor = property.getByDirection(AccessDirection.of(this));
final Callable callable = accessor.valueOrNull();
final PyType type = (callable != null) ? callable.getReturnType(context, this) : null;
return Ref.create(type);
}
}
}
else if (qualifierType instanceof PyUnionType) {
final PyUnionType unionType = (PyUnionType)qualifierType;
for (PyType type : unionType.getMembers()) {
final Ref<PyType> result = getTypeOfProperty(type, name, context);
if (result != null) {
return result;
}
}
}
@@ -549,6 +549,10 @@ public class ResolveImportUtil {
components.set(0, "collections");
return PyQualifiedName.fromComponents(components);
}
else if (head.equals("posix") || head.equals("nt")) {
components.set(0, "os");
return PyQualifiedName.fromComponents(components);
}
else if (head.equals("_functools")) {
components.set(0, "functools");
return PyQualifiedName.fromComponents(components);
@@ -565,7 +569,7 @@ public class ResolveImportUtil {
components.set(0, "datetime");
return PyQualifiedName.fromComponents(components);
}
else if (head.equals("ntpath") | head.equals("posixpath")) {
else if (head.equals("ntpath") || head.equals("posixpath") || head.equals("path")) {
final List<String> result = new ArrayList<String>();
result.add("os");
components.set(0, "path");
@@ -4,7 +4,6 @@ import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.util.io.StringRef;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.impl.PropertyBunch;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.impl.stubs.CustomTargetExpressionStub;
@@ -23,11 +22,10 @@ import java.io.IOException;
*/
public class PropertyStubStorage extends PropertyBunch<String> implements CustomTargetExpressionStub {
@Nullable
@Override
protected String translate(@NotNull PyReferenceExpression ref) {
final String name = ref.getName();
assert name != null;
return name;
protected String translate(@NotNull PyExpression ref) {
return ref.getName();
}
private static final String IMPOSSIBLE_NAME = "#";
@@ -122,7 +122,7 @@ public class PyClassType extends UserDataHolderBase implements PyCallableType {
if (resolveContext.allowProperties()) {
Property property = myClass.findProperty(name);
if (property != null) {
Maybe<PyFunction> accessor = property.getByDirection(direction);
Maybe<Callable> accessor = property.getByDirection(direction);
if (accessor.isDefined()) {
Callable accessor_code = accessor.value();
ResolveResultList ret = new ResolveResultList();
@@ -124,6 +124,12 @@ public class PyTypeChecker {
return true;
}
}
if (actual instanceof PyFunctionType && expected instanceof PyClassType) {
final PyClass superClass = ((PyClassType)expected).getPyClass();
if (superClass != null && PyNames.CALLABLE.equals(superClass.getName())) {
return true;
}
}
final String superName = expected.getName();
final String subName = actual.getName();
// TODO: No inheritance check for builtin numerics at this moment
@@ -376,7 +382,10 @@ public class PyTypeChecker {
if (callSite == null) {
return null;
}
final PsiElement parent = callSite.getParent();
PsiElement parent = callSite.getParent();
while (parent instanceof PyParenthesizedExpression) {
parent = ((PyParenthesizedExpression)parent).getContainedExpression();
}
if (parent instanceof PyCallExpression) {
return analyzeCall((PyCallExpression)parent, context);
}
@@ -6,6 +6,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.Processor;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.psi.Callable;
import com.jetbrains.python.psi.Property;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
@@ -101,10 +102,10 @@ public class RenamePyFunctionProcessor extends RenamePyElementProcessor {
}
}
private static void addRename(Map<PsiElement, String> renames, String newName, Maybe<PyFunction> accessor) {
final PyFunction function = accessor.valueOrNull();
if (function != null) {
renames.put(function, newName);
private static void addRename(Map<PsiElement, String> renames, String newName, Maybe<Callable> accessor) {
final Callable callable = accessor.valueOrNull();
if (callable instanceof PyFunction) {
renames.put(callable, newName);
}
}
}
@@ -16,7 +16,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV1() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
p = myClass.findProperty("v1");
assertNotNull(p);
assertNull(p.getDoc());
@@ -40,7 +40,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV2() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
p = myClass.findProperty("v2");
assertNotNull(p);
assertEquals("doc of v2", p.getDoc());
@@ -65,7 +65,7 @@ public class PyClassicPropertyTest extends PyTestCase {
public void testV3() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
p = myClass.findProperty("v3");
assertNotNull(p);
assertNull(p.getDoc());
@@ -73,7 +73,7 @@ public class PyClassicPropertyTest extends PyTestCase {
assertEquals("v3", site.getText());
accessor = p.getGetter();
assertFalse(accessor.isDefined());
assertTrue(accessor.isDefined());
accessor = p.getSetter();
assertTrue(accessor.isDefined());
@@ -88,7 +88,7 @@ public class PyClassicPropertyTest extends PyTestCase {
/* NOTE: we don't support this yet
public void testV4() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
p = myClass.findProperty("v4");
assertNotNull(p);
assertEquals("otherworldly", p.getDoc());
@@ -18,7 +18,7 @@ public class PyDecoratedPropertyTest extends PyTestCase {
public void testW1() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
final String name = "w1";
p = myClass.findProperty(name);
assertNotNull(p);
@@ -43,7 +43,7 @@ public class PyDecoratedPropertyTest extends PyTestCase {
public void testW2() throws Exception {
Property p;
Maybe<PyFunction> accessor;
Maybe<Callable> accessor;
final String name = "w2";
p = myClass.findProperty(name);
assertNotNull(p);
@@ -52,9 +52,11 @@ public class PyDecoratedPropertyTest extends PyTestCase {
accessor = p.getGetter();
assertTrue(accessor.isDefined());
assertNotNull(accessor.value());
assertEquals("w2", accessor.value().getName());
assertEquals("doc of "+name, accessor.value().getDocStringExpression().getStringValue());
final Callable callable = accessor.value();
assertNotNull(callable);
assertEquals("w2", callable.getName());
assertInstanceOf(callable, PyFunction.class);
assertEquals("doc of " + name, ((PyFunction)callable).getDocStringExpression().getStringValue());
accessor = p.getSetter();
assertTrue(accessor.isDefined());
@@ -104,12 +104,12 @@ public class PyStubsTest extends PyTestCase {
assertEquals("BarClass", pyClass.getName());
Property prop = pyClass.findProperty("value");
Maybe<PyFunction> maybe_function = prop.getGetter();
Maybe<Callable> maybe_function = prop.getGetter();
assertTrue(maybe_function.isDefined());
assertEquals(pyClass.getMethods()[0], maybe_function.value());
Property setvalueProp = pyClass.findProperty("setvalue");
Maybe<PyFunction> setter = setvalueProp.getSetter();
Maybe<Callable> setter = setvalueProp.getSetter();
assertTrue(setter.isDefined());
assertEquals("__set", setter.value().getName());
@@ -371,6 +371,20 @@ public class PyTypeTest extends PyTestCase {
"expr = h()\n");
}
public void testPropertyOfUnionType() {
PyExpression expr = parseExpr("def f():\n" +
" '''\n" +
" :rtype: int or slice\n" +
" '''\n" +
" raise NotImplementedError\n" +
"\n" +
"x = f()\n" +
"expr = x.start\n");
TypeEvalContext context = TypeEvalContext.slow().withTracing();
PyType actual = expr.getType(context);
assertNull(actual);
}
private PyExpression parseExpr(String text) {
myFixture.configureByText(PythonFileType.INSTANCE, text);
return myFixture.findElementByText("expr", PyExpression.class);