CallExpressionImpl extends PyTree implements CallExpression, HasTypeDependencies { @Override public InferredType type() { Symbol calleeSymbol = calleeSymbol(); if (calleeSymbol != null) { InferredType type = getType(calleeSymbol); if (type.equals(InferredTypes.anyType()) && callee.is(Kind.QUALIFIED_EXPR)) { return getDeclaredType(callee); } return type; } return InferredTypes.anyType(); } CallExpressionImpl(Expression callee, @Nullable ArgList argumentList, Token leftPar, Token rightPar); @Override Expression callee(); @Override ArgList argumentList(); @Override List<Argument> arguments(); @Override Token leftPar(); @Override Token rightPar(); @Override Kind getKind(); @Override void accept(TreeVisitor visitor); @Override List<Tree> computeChildren(); @Override InferredType type(); @Override List<Expression> typeDependencies();  }
@Test public void constructor_type() { FileInput fileInput = parse( "class A: ...", "A()"); ClassDef classDef = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CLASSDEF)); CallExpression call = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CALL_EXPR)); assertThat(call.type()).isEqualTo(InferredTypes.runtimeType(classDef.name().symbol())); }
@Test public void function_call_type() { assertThat(lastExpression("len()").type()).isEqualTo(InferredTypes.INT); }
@Test public void ambiguous_callee_symbol_type() { FileInput fileInput = parse( "class A: ...", "class A: ...", "A()"); ClassDef classDef = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CLASSDEF)); CallExpression call = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CALL_EXPR)); AmbiguousSymbol ambiguousSymbol = (AmbiguousSymbol) classDef.name().symbol(); Iterator<Symbol> iterator = ambiguousSymbol.alternatives().iterator(); InferredType firstClassType = InferredTypes.runtimeType(iterator.next()); InferredType secondClassType = InferredTypes.runtimeType(iterator.next()); assertThat(call.type()).isEqualTo(InferredTypes.or(firstClassType, secondClassType)); assertThat(call.type()).isEqualTo(firstClassType); assertThat(call.type()).isEqualTo(secondClassType); fileInput = parse( "class Base: ...", "class A(Base): ...", "class A: ...", "A()"); classDef = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CLASSDEF)); call = getLastDescendant(fileInput, t -> t.is(Tree.Kind.CALL_EXPR)); ambiguousSymbol = (AmbiguousSymbol) classDef.name().symbol(); iterator = ambiguousSymbol.alternatives().iterator(); firstClassType = InferredTypes.runtimeType(iterator.next()); secondClassType = InferredTypes.runtimeType(iterator.next()); assertThat(call.type()).isEqualTo(InferredTypes.or(firstClassType, secondClassType)); assertThat(call.type()).isNotEqualTo(firstClassType); assertThat(call.type()).isNotEqualTo(secondClassType); }
@Test public void not_callable_callee_symbol_type() { assertThat(lastExpression( "x = 42", "x()" ).type()).isEqualTo(InferredTypes.anyType()); }
@Test public void null_callee_symbol_type() { assertThat(lastExpression("x()").type()).isEqualTo(InferredTypes.anyType()); }
@Test public void method_call_with_declared_type() { assertThat(lastExpression( "def foo(param: str):", " x = param.capitalize()", " x" ).type()).isEqualTo(DECL_STR); assertThat(lastExpression( "def foo(param: A):", " x = param.capitalize()", " x" ).type()).isEqualTo(anyType()); assertThat(lastExpression( "def foo(param):", " x = param.capitalize()", " x" ).type()).isEqualTo(anyType()); assertThat(lastExpression( "def foo(param: str):", " x = param.capitalize().capitalize()", " x" ).type()).isEqualTo(anyType()); assertThat(lastExpression( "class A:", " def meth() -> int: ...", "def foo(param: A):", " x = param.meth()", " x" ).type()).isEqualTo(DECL_INT); }
@Test public void method_call_with_declared_type_union_and_optional() { ClassSymbolImpl union = new ClassSymbolImpl("Union", "typing.Union"); List<DeclaredType> typeArgs = Stream.of(DECL_INT, DECL_STR).map(DeclaredType.class::cast).collect(Collectors.toList()); assertThat(lastExpression( "from typing import Union", "class A:", " def meth() -> Union[int, str]: ...", "def foo(param: A):", " x = param.meth()", " x" ).type()).isEqualTo(new DeclaredType(union, typeArgs)); assertThat(lastExpression( "def foo(param: object):", " x = param.__reduce__()", " x" ).type()).isEqualTo(anyType()); ClassSymbolImpl optional = new ClassSymbolImpl("Optional", "typing.Optional"); typeArgs = Stream.of(DECL_STR).map(DeclaredType.class::cast).collect(Collectors.toList()); assertThat(lastExpression( "from typing import Optional", "class A:", " def meth() -> Optional[str]: ...", "def foo(param: A):", " x = param.meth()", " x" ).type()).isEqualTo(new DeclaredType(optional, typeArgs)); assertThat(lastExpression( "from typing import Optional", "class A:", " def meth() -> str: ...", "def foo(param: Optional[A]):", " x = param.meth()", " x" ).type()).isEqualTo(DECL_STR); }
@Test public void inner_class_constructor_declared_type() { InferredType type = lastExpression( "class A:", " class B: ...", "def foo(param: A):", " x = param.B()", " x" ).type(); assertThat(type).isInstanceOf(DeclaredType.class); assertThat(typeName(type)).isEqualTo("B"); }