mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Added function types syntax
This commit is contained in:
@@ -96,6 +96,12 @@ public class PyJavaClassType implements PyClassLikeType {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyType> getParameterTypes(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefinition() {
|
||||
return myDefinition;
|
||||
|
||||
@@ -39,6 +39,12 @@ public class PyJavaMethodType implements PyCallableType {
|
||||
return PyJavaTypeProvider.asPyType(myMethod.getReturnType());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyType> getParameterTypes(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
|
||||
@@ -4,6 +4,8 @@ import com.jetbrains.python.psi.PyQualifiedExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A type instances of which can possibly be called. For example, a class definition can be called, and the result of a call is a class
|
||||
* instance.
|
||||
@@ -25,4 +27,12 @@ public interface PyCallableType extends PyType {
|
||||
*/
|
||||
@Nullable
|
||||
PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite);
|
||||
|
||||
/**
|
||||
* Returns the list of parameter types.
|
||||
*
|
||||
* @return list of positional parameters or null if not applicable.
|
||||
*/
|
||||
@Nullable
|
||||
List<PyType> getParameterTypes(@NotNull TypeEvalContext context);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.jetbrains.python.psi.types;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.jetbrains.python.psi.AccessDirection;
|
||||
import com.jetbrains.python.psi.PyExpression;
|
||||
import com.jetbrains.python.psi.PyQualifiedExpression;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyCallableTypeImpl implements PyCallableType {
|
||||
@NotNull private final List<PyType> myParameterTypes;
|
||||
@Nullable private final PyType myReturnType;
|
||||
|
||||
public PyCallableTypeImpl(@NotNull List<PyType> parameterTypes, @Nullable PyType returnType) {
|
||||
myParameterTypes = parameterTypes;
|
||||
myReturnType = returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PyType getCallType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
|
||||
return myReturnType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyType> getParameterTypes(@NotNull TypeEvalContext context) {
|
||||
return myParameterTypes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
@NotNull AccessDirection direction,
|
||||
@NotNull PyResolveContext resolveContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) {
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("(%s) -> %s",
|
||||
StringUtil.join(myParameterTypes,
|
||||
new Function<PyType, String>() {
|
||||
@Override
|
||||
public String fun(PyType type) {
|
||||
return type != null ? type.getName() : "unknown";
|
||||
}
|
||||
},
|
||||
", "),
|
||||
myReturnType != null ? myReturnType.getName() : "unknown");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin(TypeEvalContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertValid(String message) {
|
||||
}
|
||||
}
|
||||
@@ -277,6 +277,12 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyType> getParameterTypes(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement resolveClassMember(@NotNull PyClass cls,
|
||||
boolean isDefinition,
|
||||
|
||||
@@ -33,6 +33,12 @@ public class PyFunctionType implements PyCallableType {
|
||||
return myCallable.getReturnType(context, callSite);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<PyType> getParameterTypes(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> resolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
|
||||
@@ -26,6 +26,6 @@ import static com.jetbrains.python.psi.types.PyTypeTokenTypes.*;
|
||||
[\r\n]+ { return NL; }
|
||||
[\ \t] { return SPACE; }
|
||||
(":py"?":class:`"[~!]?)|("`")|([A-Z]"{")|("}") { return MARKUP; }
|
||||
("or")|("of")|("from")|("to")|("<=")|[,\(\)\.\[\]|] { return OP; }
|
||||
("or")|("of")|("from")|("to")|("<=")|("->")|[,\(\)\.\[\]|] { return OP; }
|
||||
[T-Z] { return PARAMETER; }
|
||||
[A-Za-z_][A-Za-z_0-9]* { return IDENTIFIER; }
|
||||
|
||||
@@ -140,6 +140,27 @@ public class PyTypeChecker {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (actual instanceof PyCallableType && expected instanceof PyCallableType) {
|
||||
final PyCallableType expectedCallable = (PyCallableType)expected;
|
||||
final PyCallableType actualCallable = (PyCallableType)actual;
|
||||
if (expectedCallable.isCallable() && actualCallable.isCallable()) {
|
||||
final List<PyType> expectedParameters = expectedCallable.getParameterTypes(context);
|
||||
final List<PyType> actualParameters = actualCallable.getParameterTypes(context);
|
||||
if (expectedParameters != null && actualParameters != null) {
|
||||
final int size = Math.min(expectedParameters.size(), actualParameters.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (!match(expectedParameters.get(i), actualParameters.get(i), context, substitutions, recursive)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!match(expectedCallable.getCallType(context, null), actualCallable.getCallType(context, null), context, substitutions,
|
||||
recursive)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final String superName = expected.getName();
|
||||
final String subName = actual.getName();
|
||||
// TODO: No inheritance check for builtin numerics at this moment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/22/13 3:52 PM */
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/23/13 5:34 PM */
|
||||
|
||||
package com.jetbrains.python.psi.types;
|
||||
|
||||
@@ -11,7 +11,7 @@ import static com.jetbrains.python.psi.types.PyTypeTokenTypes.*;
|
||||
/**
|
||||
* This class is a scanner generated by
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
|
||||
* on 7/22/13 3:52 PM from the specification file
|
||||
* on 7/23/13 5:34 PM from the specification file
|
||||
* <tt>/home/user/src/idea/tools/lexer/../../python/src/com/jetbrains/python/psi/types/PyType.flex</tt>
|
||||
*/
|
||||
public class PyTypeLexer implements FlexLexer {
|
||||
@@ -35,12 +35,12 @@ public class PyTypeLexer implements FlexLexer {
|
||||
* Translates characters to character classes
|
||||
*/
|
||||
private static final String ZZ_CMAP_PACKED =
|
||||
"\11\0\1\2\1\1\2\0\1\1\22\0\1\2\1\13\6\0\2\26"+
|
||||
"\2\0\1\26\1\0\1\26\1\0\12\31\1\3\1\0\1\24\1\25"+
|
||||
"\3\0\23\14\7\27\1\26\1\0\1\26\1\0\1\30\1\12\1\10"+
|
||||
"\1\30\1\6\2\30\1\21\5\30\1\7\1\22\1\30\1\17\1\4"+
|
||||
"\1\30\1\20\1\11\1\23\4\30\1\5\1\30\1\15\1\26\1\16"+
|
||||
"\1\13\uff81\0";
|
||||
"\11\0\1\2\1\1\2\0\1\1\22\0\1\2\1\13\6\0\2\30"+
|
||||
"\2\0\1\30\1\26\1\30\1\0\12\33\1\3\1\0\1\24\1\25"+
|
||||
"\1\27\2\0\23\14\7\31\1\30\1\0\1\30\1\0\1\32\1\12"+
|
||||
"\1\10\1\32\1\6\2\32\1\21\5\32\1\7\1\22\1\32\1\17"+
|
||||
"\1\4\1\32\1\20\1\11\1\23\4\32\1\5\1\32\1\15\1\30"+
|
||||
"\1\16\1\13\uff81\0";
|
||||
|
||||
/**
|
||||
* Translates characters to character classes
|
||||
@@ -53,12 +53,12 @@ public class PyTypeLexer implements FlexLexer {
|
||||
private static final int [] ZZ_ACTION = zzUnpackAction();
|
||||
|
||||
private static final String ZZ_ACTION_PACKED_0 =
|
||||
"\1\0\1\1\1\2\1\0\1\3\1\4\4\3\1\0"+
|
||||
"\1\0\1\1\1\2\1\0\1\3\1\4\4\3\2\0"+
|
||||
"\1\5\1\6\2\0\1\5\1\3\2\0\1\3\5\0"+
|
||||
"\1\4";
|
||||
|
||||
private static int [] zzUnpackAction() {
|
||||
int [] result = new int[26];
|
||||
int [] result = new int[27];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -83,13 +83,13 @@ public class PyTypeLexer implements FlexLexer {
|
||||
private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
|
||||
|
||||
private static final String ZZ_ROWMAP_PACKED_0 =
|
||||
"\0\0\0\32\0\64\0\116\0\150\0\64\0\202\0\234"+
|
||||
"\0\266\0\320\0\352\0\64\0\202\0\u0104\0\u011e\0\150"+
|
||||
"\0\u0138\0\u0152\0\u016c\0\u0186\0\u01a0\0\u01ba\0\u01d4\0\u01ee"+
|
||||
"\0\u0208\0\u0222";
|
||||
"\0\0\0\34\0\70\0\124\0\160\0\70\0\214\0\250"+
|
||||
"\0\304\0\340\0\374\0\u0118\0\70\0\214\0\u0134\0\u0150"+
|
||||
"\0\160\0\u016c\0\u0188\0\u01a4\0\u01c0\0\u01dc\0\u01f8\0\u0214"+
|
||||
"\0\u0230\0\u024c\0\u0268";
|
||||
|
||||
private static int [] zzUnpackRowMap() {
|
||||
int [] result = new int[26];
|
||||
int [] result = new int[27];
|
||||
int offset = 0;
|
||||
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -114,22 +114,22 @@ public class PyTypeLexer implements FlexLexer {
|
||||
private static final String ZZ_TRANS_PACKED_0 =
|
||||
"\1\0\1\2\1\3\1\4\6\5\1\6\1\0\1\7"+
|
||||
"\1\0\1\6\1\10\1\5\1\11\1\5\1\12\1\13"+
|
||||
"\1\0\1\14\1\15\1\5\2\0\1\2\66\0\1\16"+
|
||||
"\1\0\1\17\27\0\6\5\2\0\1\5\2\0\5\5"+
|
||||
"\3\0\3\5\4\0\6\5\2\0\1\5\1\6\1\0"+
|
||||
"\5\5\3\0\3\5\4\0\6\5\2\0\1\5\2\0"+
|
||||
"\1\5\2\20\2\5\3\0\3\5\4\0\6\5\2\0"+
|
||||
"\1\5\2\0\1\5\1\21\3\5\3\0\3\5\4\0"+
|
||||
"\6\5\2\0\1\5\2\0\1\20\4\5\3\0\3\5"+
|
||||
"\25\0\1\14\11\0\1\22\33\0\1\23\26\0\6\5"+
|
||||
"\2\0\1\5\2\0\1\24\4\5\3\0\3\5\3\0"+
|
||||
"\1\25\36\0\1\26\25\0\6\5\2\0\1\5\2\0"+
|
||||
"\3\5\1\20\1\5\3\0\3\5\6\0\1\17\34\0"+
|
||||
"\1\27\31\0\1\30\23\0\1\31\40\0\1\32\32\0"+
|
||||
"\1\6\16\0";
|
||||
"\1\0\1\14\1\0\1\15\1\16\1\5\2\0\1\2"+
|
||||
"\72\0\1\17\1\0\1\20\31\0\6\5\2\0\1\5"+
|
||||
"\2\0\5\5\5\0\3\5\4\0\6\5\2\0\1\5"+
|
||||
"\1\6\1\0\5\5\5\0\3\5\4\0\6\5\2\0"+
|
||||
"\1\5\2\0\1\5\2\21\2\5\5\0\3\5\4\0"+
|
||||
"\6\5\2\0\1\5\2\0\1\5\1\22\3\5\5\0"+
|
||||
"\3\5\4\0\6\5\2\0\1\5\2\0\1\21\4\5"+
|
||||
"\5\0\3\5\25\0\1\15\35\0\1\15\11\0\1\23"+
|
||||
"\35\0\1\24\30\0\6\5\2\0\1\5\2\0\1\25"+
|
||||
"\4\5\5\0\3\5\3\0\1\26\40\0\1\27\27\0"+
|
||||
"\6\5\2\0\1\5\2\0\3\5\1\21\1\5\5\0"+
|
||||
"\3\5\6\0\1\20\36\0\1\30\33\0\1\31\25\0"+
|
||||
"\1\32\42\0\1\33\34\0\1\6\20\0";
|
||||
|
||||
private static int [] zzUnpackTrans() {
|
||||
int [] result = new int[572];
|
||||
int [] result = new int[644];
|
||||
int offset = 0;
|
||||
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -170,11 +170,11 @@ public class PyTypeLexer implements FlexLexer {
|
||||
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
|
||||
|
||||
private static final String ZZ_ATTRIBUTE_PACKED_0 =
|
||||
"\1\0\1\1\1\11\1\0\1\1\1\11\4\1\1\0"+
|
||||
"\1\0\1\1\1\11\1\0\1\1\1\11\4\1\2\0"+
|
||||
"\1\11\1\1\2\0\2\1\2\0\1\1\5\0\1\1";
|
||||
|
||||
private static int [] zzUnpackAttribute() {
|
||||
int [] result = new int[26];
|
||||
int [] result = new int[27];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -257,7 +257,7 @@ public class PyTypeLexer implements FlexLexer {
|
||||
char [] map = new char[0x10000];
|
||||
int i = 0; /* index in packed string */
|
||||
int j = 0; /* index in unpacked array */
|
||||
while (i < 104) {
|
||||
while (i < 106) {
|
||||
int count = packed.charAt(i++);
|
||||
char value = packed.charAt(i++);
|
||||
do map[j++] = value; while (--count > 0);
|
||||
|
||||
@@ -108,10 +108,11 @@ public class PyTypeParser {
|
||||
|
||||
final ForwardDeclaration<ParseResult, PyElementType> typeExpr = ForwardDeclaration.create();
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> simpleType =
|
||||
final FunctionalParser<ParseResult, PyElementType> classType =
|
||||
token(IDENTIFIER).then(many(op(".").skipThen(token(IDENTIFIER))))
|
||||
.map(new MakeSimpleType(anchor))
|
||||
.named("simple-type");
|
||||
.cached()
|
||||
.named("class-type");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> tupleType =
|
||||
op("(").skipThen(typeExpr).then(many(op(",").skipThen(typeExpr))).thenSkip(op(")"))
|
||||
@@ -154,14 +155,13 @@ public class PyTypeParser {
|
||||
.named("type-parameter");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> simpleExpr =
|
||||
simpleType
|
||||
classType
|
||||
.or(tupleType)
|
||||
.or(typeParameter)
|
||||
.cached()
|
||||
.named("simple-expr");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> paramExpr =
|
||||
simpleExpr.thenSkip(op("[")).then(typeExpr).then(many(op(",").skipThen(typeExpr))).thenSkip(op("]"))
|
||||
classType.thenSkip(op("[")).then(typeExpr).then(many(op(",").skipThen(typeExpr))).thenSkip(op("]"))
|
||||
.map(new Function<Pair<Pair<ParseResult, ParseResult>, List<ParseResult>>, ParseResult>() {
|
||||
@Override
|
||||
public ParseResult fun(Pair<Pair<ParseResult, ParseResult>, List<ParseResult>> value) {
|
||||
@@ -187,7 +187,7 @@ public class PyTypeParser {
|
||||
return EMPTY_RESULT;
|
||||
}
|
||||
})
|
||||
.or(simpleExpr.thenSkip(op("of")).then(simpleExpr)
|
||||
.or(classType.thenSkip(op("of")).then(simpleExpr)
|
||||
.map(new Function<Pair<ParseResult, ParseResult>, ParseResult>() {
|
||||
@Override
|
||||
public ParseResult fun(Pair<ParseResult, ParseResult> value) {
|
||||
@@ -205,7 +205,7 @@ public class PyTypeParser {
|
||||
return EMPTY_RESULT;
|
||||
}
|
||||
}))
|
||||
.or(simpleExpr.thenSkip(op("from")).then(simpleExpr).thenSkip(op("to")).then(simpleExpr)
|
||||
.or(classType.thenSkip(op("from")).then(simpleExpr).thenSkip(op("to")).then(simpleExpr)
|
||||
.map(new Function<Pair<Pair<ParseResult, ParseResult>, ParseResult>, ParseResult>() {
|
||||
@Override
|
||||
public ParseResult fun(Pair<Pair<ParseResult, ParseResult>, ParseResult> value) {
|
||||
@@ -222,11 +222,45 @@ public class PyTypeParser {
|
||||
return EMPTY_RESULT;
|
||||
}
|
||||
}))
|
||||
.or(simpleExpr)
|
||||
.named("param-expr");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> callableExpr =
|
||||
op("(").skipThen(maybe(typeExpr.then(many(op(",").skipThen(typeExpr))))).thenSkip(op(")")).thenSkip(op("->")).then(typeExpr)
|
||||
.map(
|
||||
new Function<Pair<Pair<ParseResult, List<ParseResult>>, ParseResult>, ParseResult>() {
|
||||
@Override
|
||||
public ParseResult fun(Pair<Pair<ParseResult, List<ParseResult>>, ParseResult> value) {
|
||||
final List<PyType> parameterTypes = new ArrayList<PyType>();
|
||||
final ParseResult returnResult = value.getSecond();
|
||||
ParseResult result;
|
||||
final Pair<ParseResult, List<ParseResult>> firstPair = value.getFirst();
|
||||
if (firstPair != null) {
|
||||
final ParseResult first = firstPair.getFirst();
|
||||
final List<ParseResult> second = firstPair.getSecond();
|
||||
result = first;
|
||||
parameterTypes.add(first.getType());
|
||||
for (ParseResult r : second) {
|
||||
result = result.merge(r);
|
||||
parameterTypes.add(r.getType());
|
||||
}
|
||||
result = result.merge(returnResult);
|
||||
}
|
||||
else {
|
||||
result = returnResult;
|
||||
}
|
||||
return result.withType(new PyCallableTypeImpl(parameterTypes, returnResult.getType()));
|
||||
}
|
||||
})
|
||||
.named("callable-expr");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> singleExpr =
|
||||
paramExpr
|
||||
.or(callableExpr)
|
||||
.or(simpleExpr)
|
||||
.named("single-expr");
|
||||
|
||||
final FunctionalParser<ParseResult, PyElementType> unionExpr =
|
||||
paramExpr.then(many(op("or").or(op("|")).skipThen(paramExpr)))
|
||||
singleExpr.then(many(op("or").or(op("|")).skipThen(singleExpr)))
|
||||
.map(new Function<Pair<ParseResult, List<ParseResult>>, ParseResult>() {
|
||||
@Override
|
||||
public ParseResult fun(Pair<ParseResult, List<ParseResult>> value) {
|
||||
|
||||
@@ -227,4 +227,33 @@ public class PyTypeParserTest extends PyTestCase {
|
||||
assertClassType(list.get(1), "str");
|
||||
assertClassType(list.get(2), "unicode");
|
||||
}
|
||||
|
||||
public void testCallableType() {
|
||||
myFixture.configureByFile("typeParser/typeParser.py");
|
||||
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "(int, T) -> T");
|
||||
assertInstanceOf(type, PyCallableType.class);
|
||||
final PyCallableType callableType = (PyCallableType)type;
|
||||
assertNotNull(callableType);
|
||||
final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
|
||||
assertInstanceOf(returnType, PyGenericType.class);
|
||||
final List<PyType> parameterTypes = callableType.getParameterTypes(getTypeEvalContext());
|
||||
assertNotNull(parameterTypes);
|
||||
assertEquals(2, parameterTypes.size());
|
||||
assertEquals("int", parameterTypes.get(0).getName());
|
||||
assertEquals("T", parameterTypes.get(1).getName());
|
||||
}
|
||||
|
||||
public void testCallableWithoutArgs() {
|
||||
myFixture.configureByFile("typeParser/typeParser.py");
|
||||
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "() -> int");
|
||||
assertInstanceOf(type, PyCallableType.class);
|
||||
final PyCallableType callableType = (PyCallableType)type;
|
||||
assertNotNull(callableType);
|
||||
final PyType returnType = callableType.getCallType(getTypeEvalContext(), null);
|
||||
assertNotNull(returnType);
|
||||
assertEquals("int", returnType.getName());
|
||||
final List<PyType> parameterTypes = callableType.getParameterTypes(getTypeEvalContext());
|
||||
assertNotNull(parameterTypes);
|
||||
assertEquals(0, parameterTypes.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,6 +582,32 @@ public class PyTypeTest extends PyTestCase {
|
||||
" pass\n");
|
||||
}
|
||||
|
||||
public void testFunctionTypeAsUnificationArgument() {
|
||||
doTest("int",
|
||||
"def map2(f, xs):\n" +
|
||||
" '''\n" +
|
||||
" :type f: (T) -> V | None\n" +
|
||||
" :type xs: collections.Iterable[T] | bytes | unicode\n" +
|
||||
" :rtype: list[V] | bytes | unicode\n" +
|
||||
" '''\n" +
|
||||
" pass\n" +
|
||||
"\n" +
|
||||
"expr = map2(lambda x: 10, ['1', '2', '3'])[0]\n");
|
||||
}
|
||||
|
||||
public void testFunctionTypeAsUnificationResult() {
|
||||
doTest("int",
|
||||
"def f(x):\n" +
|
||||
" '''\n" +
|
||||
" :type x: T\n" +
|
||||
" :rtype: () -> T\n" +
|
||||
" '''\n" +
|
||||
" pass\n" +
|
||||
"\n" +
|
||||
"g = f(10)\n" +
|
||||
"expr = g()\n");
|
||||
}
|
||||
|
||||
private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
|
||||
return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user