Merge branch 'master' of git.labs.intellij.net:idea/ultimate

This commit is contained in:
Oleg Shpynov
2010-07-09 19:01:43 +04:00
17 changed files with 312 additions and 50 deletions
+163 -8
View File
@@ -19,7 +19,7 @@ all this too.
"""
from datetime import datetime
OUR_OWN_DATETIME = datetime(2010, 6, 3, 17, 13, 12) # datetime.now() of edit time
OUR_OWN_DATETIME = datetime(2010, 7, 9, 16, 1, 5) # datetime.now() of edit time
# we could use script's ctime, but the actual running copy may have it all wrong.
#
# Note: DON'T FORGET TO UPDATE!
@@ -347,7 +347,7 @@ optionalPart << (
| ellipsis
)
# this is our ideal target, with balancing paren and a multiline rest of doc.
# this is our ideal target, with balancing paren and a multiline rest of doc.
paramSeqAndRest = paramSeq + Suppress(')') + Suppress(Optional(Regex(".*(?s)")))
def transformSeq(results, toplevel=True):
@@ -555,6 +555,146 @@ class ModuleRedeclarator(object):
PREDEFINED_MOD_CLASS_SIGS = {
("datetime", "timedelta", "__new__") : "(cls, days=None, seconds=None, microseconds=None, milliseconds=None, minutes=None, hours=None, weeks=None)",
}
# known properties of modules
# {{"module": {"class", "property" : ("letters", "getter")}},
# where letters is any set of r,w,d (read, write, del) and "getter" is a source of typed getter.
# if vlue is None, the property should be omitted.
# read-only properties that return an object are not listed.
G_OBJECT = "lambda self: object()"
G_TYPE = "lambda self: type(object)"
G_DICT = "lambda self: {}"
G_STR = "lambda self: ''"
G_TUPLE = "lambda self: tuple()"
G_FLOAT = "lambda self: 0.0"
G_INT = "lambda self: 0"
G_BOOL = "lambda self: True"
KNOWN_PROPS = {
BUILTIN_MOD_NAME: {
("object", '__class__'): ('r', G_TYPE),
("BaseException", '__dict__'): ('r', G_DICT),
("BaseException", 'message'): ('rwd', G_STR),
("BaseException",'args'): ('r', G_TUPLE),
('complex','real'): ('r', G_FLOAT),
('complex','imag'): ('r', G_FLOAT),
("EnvironmentError", 'errno'): ('rwd', G_INT),
("EnvironmentError", 'message'): ('rwd', G_STR),
("EnvironmentError", 'strerror'): ('rwd', G_INT),
("EnvironmentError", 'filename'): ('rwd', G_STR),
("file", 'softspace'): ('r', G_BOOL),
("file", 'name'): ('r', G_STR),
("file", 'encoding'): ('r', G_STR),
("file", 'mode'): ('r', G_STR),
("file", 'closed'): ('r', G_BOOL),
("file", 'newlines'): ('r', G_STR),
("SyntaxError", 'text'): ('rwd', G_STR),
("SyntaxError", 'print_file_and_line'): ('rwd', G_BOOL),
("SyntaxError", 'filename'): ('rwd', G_STR),
("SyntaxError", 'lineno'): ('rwd', G_INT),
("SyntaxError", 'offset'): ('rwd', G_INT),
("SyntaxError", 'msg'): ('rwd', G_STR),
("SyntaxError", 'message'): ('rwd', G_STR),
("slice", 'start'): ('r', G_INT),
("slice", 'step'): ('r', G_INT),
("slice", 'stop'): ('r', G_INT),
("super", '__thisclass__'): ('r', G_TYPE),
("super", '__self__'): ('r', G_TYPE),
("super", '__self_class__'): ('r', G_TYPE),
("SystemExit", 'message'): ('rwd', G_STR),
("SystemExit", 'code'): ('rwd', G_OBJECT),
("type", '__basicsize__'): ('r', G_INT),
("type", '__itemsize__'): ('r', G_INT),
("type", '__base__'): ('r', G_TYPE),
("type", '__flags__'): ('r', G_INT),
("type", '__mro__'): ('r', G_TUPLE),
("type", '__bases__'): ('r', G_TUPLE),
("type", '__dictoffset__'): ('r', G_INT),
("type", '__dict__'): ('r', G_DICT),
("type", '__name__'): ('r', G_STR),
("type", '__weakrefoffset__'): ('r', G_INT),
("UnicodeDecodeError", '__basicsize__'): None,
("UnicodeDecodeError", '__itemsize__'): None,
("UnicodeDecodeError", '__base__'): None,
("UnicodeDecodeError", '__flags__'): ('rwd', G_INT),
("UnicodeDecodeError", '__mro__'): None,
("UnicodeDecodeError", '__bases__'): None,
("UnicodeDecodeError", '__dictoffset__'): None,
("UnicodeDecodeError", '__dict__'): None,
("UnicodeDecodeError", '__name__'): None,
("UnicodeDecodeError", '__weakrefoffset__'): None,
("UnicodeEncodeError", 'end'): ('rwd', G_INT),
("UnicodeEncodeError", 'encoding'): ('rwd', G_STR),
("UnicodeEncodeError", 'object'): ('rwd', G_OBJECT),
("UnicodeEncodeError", 'start'): ('rwd', G_INT),
("UnicodeEncodeError", 'reason'): ('rwd', G_STR),
("UnicodeEncodeError", 'message'): ('rwd', G_STR),
("UnicodeTranslateError", 'end'): ('rwd', G_INT),
("UnicodeTranslateError", 'encoding'): ('rwd', G_STR),
("UnicodeTranslateError", 'object'): ('rwd', G_OBJECT),
("UnicodeTranslateError", 'start'): ('rwd', G_INT),
("UnicodeTranslateError", 'reason'): ('rwd', G_STR),
("UnicodeTranslateError", 'message'): ('rwd', G_STR),
},
'_ast': {
("AST", '__dict__'): ('rd', G_DICT),
},
'posix': {
("statvfs_result", 'f_flag'): ('r', G_INT),
("statvfs_result", 'f_bavail'): ('r', G_INT),
("statvfs_result", 'f_favail'): ('r', G_INT),
("statvfs_result", 'f_files'): ('r', G_INT),
("statvfs_result", 'f_frsize'): ('r', G_INT),
("statvfs_result", 'f_blocks'): ('r', G_INT),
("statvfs_result", 'f_ffree'): ('r', G_INT),
("statvfs_result", 'f_bfree'): ('r', G_INT),
("statvfs_result", 'f_namemax'): ('r', G_INT),
("statvfs_result", 'f_bsize'): ('r', G_INT),
("stat_result", 'st_ctime'): ('r', G_INT),
("stat_result", 'st_rdev'): ('r', G_INT),
("stat_result", 'st_mtime'): ('r', G_INT),
("stat_result", 'st_blocks'): ('r', G_INT),
("stat_result", 'st_gid'): ('r', G_INT),
("stat_result", 'st_nlink'): ('r', G_INT),
("stat_result", 'st_ino'): ('r', G_INT),
("stat_result", 'st_blksize'): ('r', G_INT),
("stat_result", 'st_dev'): ('r', G_INT),
("stat_result", 'st_size'): ('r', G_INT),
("stat_result", 'st_mode'): ('r', G_INT),
("stat_result", 'st_uid'): ('r', G_INT),
("stat_result", 'st_atime'): ('r', G_INT),
},
"pwd": {
("struct_pwent", 'pw_dir'): ('r', G_STR),
("struct_pwent", 'pw_gid'): ('r', G_INT),
("struct_pwent", 'pw_passwd'): ('r', G_STR),
("struct_pwent", 'pw_gecos'): ('r', G_STR),
("struct_pwent", 'pw_shell'): ('r', G_STR),
("struct_pwent", 'pw_name'): ('r', G_STR),
("struct_pwent", 'pw_uid'): ('r', G_INT),
("struct_passwd", 'pw_dir'): ('r', G_STR),
("struct_passwd", 'pw_gid'): ('r', G_INT),
("struct_passwd", 'pw_passwd'): ('r', G_STR),
("struct_passwd", 'pw_gecos'): ('r', G_STR),
("struct_passwd", 'pw_shell'): ('r', G_STR),
("struct_passwd", 'pw_name'): ('r', G_STR),
("struct_passwd", 'pw_uid'): ('r', G_INT),
},
"thread": {
("_local", '__dict__'): None
},
"xxsubtype": {
("spamdict", 'state'): ('r', G_INT),
("spamlist", 'state'): ('r', G_INT),
},
"zipimport": {
("zipimporter", 'prefix'): ('r', G_STR),
("zipimporter", 'archive'): ('r', G_STR),
("zipimporter", '_files'): ('r', G_DICT),
},
}
# Some builtin classes effectively change __init__ signature without overriding it.
# This callable serves as a placeholder to be replaced via REDEFINED_BUILTIN_SIGS
@@ -948,10 +1088,10 @@ class ModuleRedeclarator(object):
self.out("class " + p_name + base_def + ":", indent)
self.outDocAttr(p_class, indent+1)
# inner parts
methods = {}
properties = {}
others = {}
if hasattr(p_class, "__dict__"):
methods = {}
properties = {}
others = {}
we_are_the_base_class = p_modname == BUILTIN_MOD_NAME and p_name in ("object", FAKE_CLASSOBJ_NAME)
for item_name in p_class.__dict__:
if item_name in ("__doc__", "__module__"):
@@ -978,9 +1118,24 @@ class ModuleRedeclarator(object):
item = methods[item_name]
self.redoFunction(item, item_name, indent+1, p_class, p_modname)
#
known_props = self.KNOWN_PROPS.get(p_modname, {})
a_setter = "lambda self, v: None"
a_deleter = "lambda self: None"
for item_name in sortedNoCase(properties.keys()):
item = properties[item_name]
self.out(item_name + " = property(None, None, None)", indent+1) # TODO: handle docstring
prop_key = (p_name, item_name)
if known_props.has_key(prop_key):
prop_descr = known_props.get(prop_key, None)
if prop_descr is None:
continue # explicitly omitted
acc_line, getter = prop_descr
accessors = []
accessors.append("r" in acc_line and getter or "None")
accessors.append("w" in acc_line and a_setter or "None")
accessors.append("d" in acc_line and a_deleter or "None")
self.out(item_name + " = property(" + ", ".join(accessors) + ")", indent+1)
else:
self.out(item_name + " = property(lambda self: object(), None, None) # default", indent+1)
# TODO: handle docstring
if properties:
self.out("", 0) # empty line after the block
#
@@ -1015,7 +1170,7 @@ class ModuleRedeclarator(object):
if hasattr(item, "__name__"):
self.out("import " + item.__name__ + " as " + item_name + " # refers to " + str(item))
else:
self.out(item_name + " = None # XXX name unknown, refers to " + str(item))
self.out(item_name + " = None # ??? name unknown, refers to " + str(item))
self.out("", 0) # empty line after imports
# group what else we have into buckets
vars_simple = {}
@@ -49,4 +49,9 @@ public class PyJavaClassType implements PyType {
return myClass.getName();
else return null;
}
@Override
public boolean isBuiltin() {
return false; // TODO: JSDK's types could be considered built-in.
}
}
@@ -20,7 +20,7 @@ public class PyTokenTypes {
public static final PyElementType END_OF_LINE_COMMENT = new PyElementType("END_OF_LINE_COMMENT");
public static final PyElementType AND_KEYWORD = new PyElementType("AND_KEYWORD");
public static final PyElementType AND_KEYWORD = new PyElementType("AND_KEYWORD", "__and__");
public static final PyElementType AS_KEYWORD = new PyElementType("AS_KEYWORD");
public static final PyElementType ASSERT_KEYWORD = new PyElementType("ASSERT_KEYWORD");
public static final PyElementType BREAK_KEYWORD = new PyElementType("BREAK_KEYWORD");
@@ -42,7 +42,7 @@ public class PyTokenTypes {
public static final PyElementType IS_KEYWORD = new PyElementType("IS_KEYWORD");
public static final PyElementType LAMBDA_KEYWORD = new PyElementType("LAMBDA_KEYWORD");
public static final PyElementType NOT_KEYWORD = new PyElementType("NOT_KEYWORD");
public static final PyElementType OR_KEYWORD = new PyElementType("OR_KEYWORD");
public static final PyElementType OR_KEYWORD = new PyElementType("OR_KEYWORD", "__or__");
public static final PyElementType PASS_KEYWORD = new PyElementType("PASS_KEYWORD");
public static final PyElementType PRINT_KEYWORD = new PyElementType("PRINT_KEYWORD");
public static final PyElementType RAISE_KEYWORD = new PyElementType("RAISE_KEYWORD");
@@ -75,26 +75,26 @@ public class PyTokenTypes {
public static final PyElementType STRING_LITERAL = new PyElementType("STRING_LITERAL");
// Operators
public static final PyElementType PLUS = new PyElementType("PLUS");// +
public static final PyElementType MINUS = new PyElementType("MINUS");// -
public static final PyElementType MULT = new PyElementType("MULT");// *
public static final PyElementType EXP = new PyElementType("EXP");// **
public static final PyElementType DIV = new PyElementType("DIV"); // /
public static final PyElementType FLOORDIV = new PyElementType("FLOORDIV"); // //
public static final PyElementType PERC = new PyElementType("PERC");// %
public static final PyElementType LTLT = new PyElementType("LTLT");// <<
public static final PyElementType GTGT = new PyElementType("GTGT");// >>
public static final PyElementType AND = new PyElementType("AND");// &
public static final PyElementType OR = new PyElementType("OR");// |
public static final PyElementType XOR = new PyElementType("XOR");// ^
public static final PyElementType TILDE = new PyElementType("TILDE");// ~
public static final PyElementType LT = new PyElementType("LT");// <
public static final PyElementType GT = new PyElementType("GT");// >
public static final PyElementType LE = new PyElementType("LE");// <=
public static final PyElementType GE = new PyElementType("GE");// >=
public static final PyElementType EQEQ = new PyElementType("EQEQ");// ==
public static final PyElementType NE = new PyElementType("NE");// !=
public static final PyElementType NE_OLD = new PyElementType("NE_OLD");// <>
public static final PyElementType PLUS = new PyElementType("PLUS", "__add__");// +
public static final PyElementType MINUS = new PyElementType("MINUS", "__sub__");// -
public static final PyElementType MULT = new PyElementType("MULT", "__mul__");// *
public static final PyElementType EXP = new PyElementType("EXP", "__pow__");// **
public static final PyElementType DIV = new PyElementType("DIV", "__div__"); // /
public static final PyElementType FLOORDIV = new PyElementType("FLOORDIV", "__floordiv__"); // //
public static final PyElementType PERC = new PyElementType("PERC", "__mod__");// %
public static final PyElementType LTLT = new PyElementType("LTLT", "__lshift__");// <<
public static final PyElementType GTGT = new PyElementType("GTGT", "__rshift__");// >>
public static final PyElementType AND = new PyElementType("AND", "__and__");// &
public static final PyElementType OR = new PyElementType("OR", "__or__");// |
public static final PyElementType XOR = new PyElementType("XOR", "__xor__");// ^
public static final PyElementType TILDE = new PyElementType("TILDE", "__invert__");// ~
public static final PyElementType LT = new PyElementType("LT", "__lt__");// <
public static final PyElementType GT = new PyElementType("GT", "__gt__");// >
public static final PyElementType LE = new PyElementType("LE", "__le__");// <=
public static final PyElementType GE = new PyElementType("GE", "__ge__");// >=
public static final PyElementType EQEQ = new PyElementType("EQEQ", "__eq__");// ==
public static final PyElementType NE = new PyElementType("NE", "__ne__");// !=
public static final PyElementType NE_OLD = new PyElementType("NE_OLD", "__ne__");// <>
// Delimiters
public static final PyElementType LPAR = new PyElementType("LPAR");// (
@@ -49,11 +49,11 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
cat.append("class ").append(cls_name).append("\n ");
// It would be nice to have class import info here, but we don't know the ctrl+hovered reference and context
}
return describeFunction(func, LSame2, ", ", LSame2, LSame1).toString();
return describeDecorators(func, LSame2, ", ", LSame1).add(describeFunction(func, LSame2, LSame1)).toString();
}
else if (element instanceof PyClass) {
PyClass cls = (PyClass)element;
return describeClass(cls, LSame2).toString();
return describeDecorators(cls, LSame2, ", ", LSame1).add(describeClass(cls, LSame2)).toString();
}
return null;
}
@@ -75,18 +75,10 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
*/
private static ChainIterable<String> describeFunction(
PyFunction fun,
FP.Lambda1<Iterable<String>, Iterable<String>> deco_name_wrapper,
String deco_separator,
FP.Lambda1<Iterable<String>, Iterable<String>> func_name_wrapper,
FP.Lambda1<String, String> escaper
) {
ChainIterable<String> cat = new ChainIterable<String>(null);
PyDecoratorList deco_list = fun.getDecoratorList();
if (deco_list != null) {
for (PyDecorator deco : deco_list.getDecorators()) {
cat.add(describeDeco(deco, deco_name_wrapper, escaper)).add(deco_separator); // can't easily pass describeDeco to map() %)
}
}
cat.add("def ").addWith(func_name_wrapper, $(fun.getName()));
cat.add(escaper.apply(PyUtil.getReadableRepr(fun.getParameterList(), false)));
final PyType returnType = fun.getReturnType();
@@ -96,6 +88,20 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
return cat;
}
private static ChainIterable<String> describeDecorators(
PyDecoratable what, FP.Lambda1<Iterable<String>, Iterable<String>> deco_name_wrapper,
String deco_separator, FP.Lambda1<String, String> escaper
) {
ChainIterable<String> cat = new ChainIterable<String>();
PyDecoratorList deco_list = what.getDecoratorList();
if (deco_list != null) {
for (PyDecorator deco : deco_list.getDecorators()) {
cat.add(describeDeco(deco, deco_name_wrapper, escaper)).add(deco_separator); // can't easily pass describeDeco to map() %)
}
}
return cat;
}
/**
* Creates a HTML description of function definition.
* @param cls the class
@@ -112,7 +118,6 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
if (ancestors.length > 0) {
cat.add("(").add(interleave(FP.map(LReadableRepr, ancestors), ", ")).add(")");
}
// TODO: for py3k, show decorators
return cat;
}
@@ -260,6 +265,7 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
// doc of what?
if (followed instanceof PyClass) {
cls = (PyClass)followed;
doc_cat.add(describeDecorators(cls, TagItalic, BR, LCombUp));
doc_cat.addWith(TagSmall, describeClass(cls, TagBold));
}
else if (followed instanceof PyFunction) {
@@ -269,7 +275,7 @@ public class PythonDocumentationProvider extends QuickDocumentationProvider {
if (cls != null) doc_cat.addWith(TagSmall, $("class ", cls.getName(), BR));
}
else cls = null;
doc_cat.add(describeFunction(fun, TagItalic, BR, TagBold, LCombUp));
doc_cat.add(describeDecorators(fun, TagItalic, BR, LCombUp)).add(describeFunction(fun, TagBold, LCombUp));
if (docString == null) {
addInheritedDocString(fun, cls, doc_cat, epilog_cat);
}
@@ -7,6 +7,9 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.console.PydevConsoleRunner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -56,6 +59,27 @@ public class PyStatementEffectInspection extends PyInspection {
return;
}
}
else if (expression instanceof PyBinaryExpression) {
PyBinaryExpression binary = (PyBinaryExpression)expression;
String method = binary.getOperator().getSpecialMethodName();
if (method != null) {
// maybe the op is overridden and may produce side effects, like cout << "hello"
PyType type = binary.getLeftExpression().getType(TypeEvalContext.fast());
if (type != null && ! type.isBuiltin() && type.resolveMember(method, AccessDirection.READ) != null) {
return;
}
final PyExpression rhs = binary.getRightExpression();
if (rhs != null) {
type = rhs.getType(TypeEvalContext.fast());
if (type != null) {
String rmethod = "__r" + method.substring(2); // __add__ -> __radd__
if (! type.isBuiltin() && type.resolveMember(rmethod, AccessDirection.READ) != null) {
return;
}
}
}
}
}
final PyTryPart tryPart = PsiTreeUtil.getParentOfType(node, PyTryPart.class);
if (tryPart != null) {
@@ -16,7 +16,9 @@ import java.util.List;
/**
* Represents a class declaration in source.
*/
public interface PyClass extends PsiNamedElement, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>, ScopeOwner {
public interface PyClass extends
PsiNamedElement, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>, ScopeOwner, PyDecoratable
{
@Nullable
ASTNode getNameNode();
@@ -101,8 +103,6 @@ public interface PyClass extends PsiNamedElement, PyStatement, NameDefiner, PyDo
*/
boolean isSubclass(PyClass parent);
@Nullable
PyDecoratorList getDecoratorList();
String getQualifiedName();
@@ -0,0 +1,13 @@
package com.jetbrains.python.psi;
import org.jetbrains.annotations.Nullable;
/**
* TODO: Add description
* User: dcheryasov
* Date: Jul 8, 2010 3:48:14 AM
*/
public interface PyDecoratable {
@Nullable
PyDecoratorList getDecoratorList();
}
@@ -18,15 +18,23 @@ public class PyElementType extends IElementType {
private static final Class[] PARAMETER_TYPES = new Class[]{ASTNode.class};
private Constructor<? extends PsiElement> myConstructor;
private String mySpecialMethodName;
public PyElementType(@NotNull @NonNls String debugName) {
super(debugName, PythonFileType.INSTANCE.getLanguage());
}
public PyElementType(@NonNls String debugName, Class<? extends PsiElement> psiElementClass) {
this(debugName);
_psiElementClass = psiElementClass;
}
public PyElementType(@NotNull @NonNls String debugName, @NotNull @NonNls String specialMethodName) {
this(debugName);
mySpecialMethodName = specialMethodName;
}
@Nullable
public PsiElement createElement(ASTNode node) {
if (_psiElementClass == null) {
@@ -45,6 +53,13 @@ public class PyElementType extends IElementType {
}
}
/**
* @return name of special method for operation marked by this token; e.g. "__add__" for "+".
*/
public String getSpecialMethodName() {
return mySpecialMethodName;
}
@Override
public String toString() {
return "Py:" + super.toString();
@@ -17,8 +17,7 @@ import org.jetbrains.annotations.Nullable;
public interface PyFunction
extends
PsiNamedElement, StubBasedPsiElement<PyFunctionStub>,
PsiNameIdentifierOwner, PyStatement, Callable, NameDefiner, PyDocStringOwner, ScopeOwner
{
PsiNameIdentifierOwner, PyStatement, Callable, NameDefiner, PyDocStringOwner, ScopeOwner, PyDecoratable {
PyFunction[] EMPTY_ARRAY = new PyFunction[0];
/**
@@ -36,9 +35,6 @@ extends
@Nullable
PyClass getContainingClass();
@Nullable
PyDecoratorList getDecoratorList();
/**
* Returns true if the function is a top-level class (its parent is its containing file).
*
@@ -231,6 +231,11 @@ public class PyClassType implements PyType {
}
}
@Override
public boolean isBuiltin() {
return PyBuiltinCache.getInstance(myClass).hasInBuiltins(myClass);
}
@NotNull
public Set<String> getPossibleInstanceMembers() {
Set<String> ret = new HashSet<String>();
@@ -55,4 +55,9 @@ public class PyImportedModuleType implements PyType {
public String getName() {
return "PyImportedModuleType:" + myImportedModule.toString();
}
@Override
public boolean isBuiltin() {
return false; // no module can be imported from builtins
}
}
@@ -119,6 +119,11 @@ public class PyModuleType implements PyType { // Maybe make it a PyClassType ref
else return null;
}
@Override
public boolean isBuiltin() {
return true;
}
@NotNull
public static Set<String> getPossibleInstanceMembers() {
return ourPossibleFields;
@@ -31,4 +31,9 @@ public class PyNoneType implements PyType { // TODO must extend ClassType. It's
public String getName() {
return "None";
}
@Override
public boolean isBuiltin() {
return true;
}
}
@@ -3,6 +3,7 @@ package com.jetbrains.python.psi.types;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.Callable;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import org.jetbrains.annotations.Nullable;
/**
@@ -23,4 +24,10 @@ public class PyReturnTypeReference extends PyTypeReferenceImpl {
public String getName() {
return "return type of " + myCallable.getPresentation().getPresentableText();
}
@Override
public boolean isBuiltin() {
PyType type = myCallable.getReturnType();
return type != null && type.isBuiltin();
}
}
@@ -33,6 +33,11 @@ public class PyTupleType extends PyClassType implements PySubscriptableType {
}, ",") + ")";
}
@Override
public boolean isBuiltin() {
return true;
}
public PyType getElementType(PyExpression index, TypeEvalContext context) {
final Object value = PyConstantExpressionEvaluator.evaluate(index);
if (value instanceof Integer) {
@@ -48,4 +48,9 @@ public interface PyType {
@Nullable
String getName();
/**
* @return true if the type is a known built-in type.
*/
boolean isBuiltin();
}
@@ -55,6 +55,17 @@ public class PyUnionType implements PyType {
}, ", ") + ")";
}
/**
* @return true if all types in the union are built-in.
*/
@Override
public boolean isBuiltin() {
for (PyType one : myMembers) {
if (! one.isBuiltin()) return false;
}
return true;
}
@Nullable
public static PyType union(PyType type1, PyType type2) {
if (type1 instanceof PyTupleType && type2 instanceof PyTupleType) {