/* * 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 members = type.getMembers(); assertEquals(2, members.size()); final List list = new ArrayList(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 types = new ArrayList(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 members = new ArrayList(((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 members = type.getMembers(); assertEquals(3, members.size()); final List list = new ArrayList(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 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 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); } }