blob: 7db230a1d7c1e1d7c155d8a5cf4925b95d4536e3 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.types.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author yole
*/
public class PyTypeParserTest extends PyTestCase {
public void testClassType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject");
assertClassType(type, "MyObject");
}
private static void assertClassType(PyType type, final String name) {
assertNotNull(type);
assertEquals(name, ((PyClassType)type).getPyClass().getName());
}
public void testTupleType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyTupleType type = (PyTupleType)PyTypeParser.getTypeByName(myFixture.getFile(), "(str, MyObject)");
assertEquals(2, type.getElementCount());
assertClassType(type.getElementType(0), "str");
assertClassType(type.getElementType(1), "MyObject");
}
public void testListType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "list of MyObject");
assertClassType(type, "list");
assertClassType(type.getElementType(getTypeEvalContext()), "MyObject");
}
public void testDictType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "dict from str to MyObject");
assertNotNull(type);
assertClassType(type, "dict");
final PyType elementType = type.getElementType(getTypeEvalContext());
assertInstanceOf(elementType, PyTupleType.class);
final PyTupleType tupleType = (PyTupleType)elementType;
assertEquals(2, tupleType.getElementCount());
assertClassType(tupleType.getElementType(0), "str");
assertClassType(tupleType.getElementType(1), "MyObject");
}
private TypeEvalContext getTypeEvalContext() {
return TypeEvalContext.userInitiated(myFixture.getFile());
}
public void testUnionType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyUnionType type = (PyUnionType)PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject or str");
assertNotNull(type);
final Collection<PyType> members = type.getMembers();
assertEquals(2, members.size());
final List<PyType> list = new ArrayList<PyType>(members);
assertClassType(list.get(0), "MyObject");
assertClassType(list.get(1), "str");
}
public void testNoneType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "None");
assertNotNull(type);
assertInstanceOf(type, PyNoneType.class);
}
public void testIntegerType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "integer");
assertClassType(type, "int");
}
public void testStringType() {
// Python 2
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "string");
assertNotNull(type);
assertInstanceOf(type, PyUnionType.class);
final PyUnionType unionType = (PyUnionType)type;
final ArrayList<PyType> types = new ArrayList<PyType>(unionType.getMembers());
assertClassType(types.get(0), "str");
assertClassType(types.get(1), "unicode");
}
public void testBooleanType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "boolean");
assertClassType(type, "bool");
}
public void testDictionaryType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "dictionary");
assertClassType(type, "dict");
}
public void testQualifiedNotImportedType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyTypeParser.ParseResult result = PyTypeParser.parse(myFixture.getFile(), "collections.Iterable");
final PyType type = result.getType();
assertClassType(type, "Iterable");
assertEquals(2, result.getTypes().size());
}
public void testUnqualifiedNotImportedType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "Iterable");
assertClassType(type, "Iterable");
}
public void testTypeSubparts() {
myFixture.configureByFile("typeParser/typeParser.py");
final String s = "list of (MyObject, collections.Iterable of MyObject, int) or None";
PyTypeParser.ParseResult result = PyTypeParser.parse(myFixture.getFile(), s);
assertEquals(7, result.getTypes().values().size());
}
public void testGenericType() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "T");
assertNotNull(type);
assertInstanceOf(type, PyGenericType.class);
assertEquals("T", type.getName());
}
// PY-4223
public void testSphinxFormattedType() {
myFixture.configureByFile("typeParser/typeParser.py");
final String s = "(MyObject, :class:`MyObject`, :py:class:`MyObject`, :class:`!MyObject`, :py:class:`~MyObject`)";
final PyTupleType type = (PyTupleType)PyTypeParser.getTypeByName(myFixture.getFile(), s);
assertNotNull(type);
final int n = type.getElementCount();
assertEquals(5, n);
for (int i = 0; i < n; i++) {
assertClassType(type.getElementType(i), "MyObject");
}
}
// PY-7950
public void testUnionWithUnresolved() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "Unresolved or int");
assertNotNull(type);
assertInstanceOf(type, PyUnionType.class);
final List<PyType> members = new ArrayList<PyType>(((PyUnionType)type).getMembers());
assertEquals(2, members.size());
assertNull(members.get(0));
assertClassType(members.get(1), "int");
}
public void testUnionParamPriority() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType t1 = PyTypeParser.getTypeByName(myFixture.getFile(), "list of int or list of str");
assertInstanceOf(t1, PyUnionType.class);
final PyType t2 = PyTypeParser.getTypeByName(myFixture.getFile(), "list of str or int");
assertInstanceOf(t2, PyUnionType.class);
}
public void testParenthesesPriority() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "list of (str or int)");
assertInstanceOf(type, PyCollectionType.class);
final PyCollectionType collectionType = (PyCollectionType)type;
assertNotNull(collectionType);
assertEquals("list", collectionType.getName());
final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
assertInstanceOf(elementType, PyUnionType.class);
}
public void testBoundedGeneric() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "T <= str or unicode");
assertNotNull(type);
assertInstanceOf(type, PyGenericType.class);
final PyGenericType genericType = (PyGenericType)type;
final PyType bound = genericType.getBound();
assertInstanceOf(bound, PyUnionType.class);
}
public void testBracketSingleParam() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "list[int]");
assertInstanceOf(type, PyCollectionType.class);
final PyCollectionType collectionType = (PyCollectionType)type;
assertNotNull(collectionType);
assertEquals("list", collectionType.getName());
final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
assertNotNull(elementType);
assertEquals("int", elementType.getName());
}
public void testBracketMultipleParams() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyType type = PyTypeParser.getTypeByName(myFixture.getFile(), "dict[str, int]");
assertInstanceOf(type, PyCollectionType.class);
final PyCollectionType collectionType = (PyCollectionType)type;
assertNotNull(collectionType);
assertEquals("dict", collectionType.getName());
final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
assertNotNull(elementType);
assertInstanceOf(elementType, PyTupleType.class);
final PyTupleType tupleType = (PyTupleType)elementType;
final PyType first = tupleType.getElementType(0);
assertNotNull(first);
assertEquals("str", first.getName());
final PyType second = tupleType.getElementType(1);
assertNotNull(second);
assertEquals("int", second.getName());
}
public void testUnionOrOperator() {
myFixture.configureByFile("typeParser/typeParser.py");
final PyUnionType type = (PyUnionType)PyTypeParser.getTypeByName(myFixture.getFile(), "MyObject | str | unicode");
assertNotNull(type);
final Collection<PyType> members = type.getMembers();
assertEquals(3, members.size());
final List<PyType> list = new ArrayList<PyType>(members);
assertClassType(list.get(0), "MyObject");
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 TypeEvalContext context = getTypeEvalContext();
final PyType returnType = callableType.getReturnType(context);
assertInstanceOf(returnType, PyGenericType.class);
final List<PyCallableParameter> parameterTypes = callableType.getParameters(context);
assertNotNull(parameterTypes);
assertEquals(2, parameterTypes.size());
final PyType type0 = parameterTypes.get(0).getType(context);
assertNotNull(type0);
assertEquals("int", type0.getName());
final PyType type1 = parameterTypes.get(1).getType(context);
assertNotNull(type1);
assertEquals("T", type1.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.getReturnType(getTypeEvalContext());
assertNotNull(returnType);
assertEquals("int", returnType.getName());
final List<PyCallableParameter> parameterTypes = callableType.getParameters(getTypeEvalContext());
assertNotNull(parameterTypes);
assertEquals(0, parameterTypes.size());
}
public void testQualifiedUserSkeletonsClass() {
doTest("Iterator[int]", "collections.Iterator[int]");
}
public void testUnqualifiedUserSkeletonsClass() {
doTest("Iterator[int]", "Iterator[int]");
}
private void doTest(final String expectedType, final String text) {
myFixture.configureByFile("typeParser/typeParser.py");
final PsiFile file = myFixture.getFile();
final PyType type = PyTypeParser.getTypeByName(file, text);
TypeEvalContext context = TypeEvalContext.userInitiated(file).withTracing();
final String actualType = PythonDocumentationProvider.getTypeName(type, context);
assertEquals(expectedType, actualType);
}
}