PY-16987 Google and Numpy docstrings return null as parameter type if it wasn't speci...
[idea/community.git] / python / testSrc / com / jetbrains / python / Py3TypeTest.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python;
17
18 import com.intellij.testFramework.LightProjectDescriptor;
19 import com.jetbrains.python.documentation.PythonDocumentationProvider;
20 import com.jetbrains.python.fixtures.PyTestCase;
21 import com.jetbrains.python.psi.LanguageLevel;
22 import com.jetbrains.python.psi.PyExpression;
23 import com.jetbrains.python.psi.types.PyType;
24 import com.jetbrains.python.psi.types.TypeEvalContext;
25
26 /**
27  * @author vlan
28  */
29 public class Py3TypeTest extends PyTestCase {
30   public static final String TEST_DIRECTORY = "/types/";
31
32   @Override
33   protected LightProjectDescriptor getProjectDescriptor() {
34     return ourPy3Descriptor;
35   }
36
37   // PY-6702
38   public void testYieldFromType() {
39     runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
40       @Override
41       public void run() {
42         doTest("Union[str, int, float]",
43                "def subgen():\n" +
44                "    for i in [1, 2, 3]:\n" +
45                "        yield i\n" +
46                "\n" +
47                "def gen():\n" +
48                "    yield 'foo'\n" +
49                "    yield from subgen()\n" +
50                "    yield 3.14\n" +
51                "\n" +
52                "for expr in gen():\n" +
53                "    pass\n");
54       }
55     });
56   }
57
58   public void testAwaitAwaitable() {
59     runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() {
60       @Override
61       public void run() {
62         doTest("int",
63                "class C:\n" +
64                "    def __await__(self):\n" +
65                "        yield 'foo'\n" +
66                "        return 0\n" +
67                "\n" +
68                "async def foo():\n" +
69                "    c = C()\n" +
70                "    expr = await c\n");
71       }
72     });
73   }
74
75   public void testAsyncDefReturnType() {
76     runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() {
77       @Override
78       public void run() {
79         doTest("__coroutine[int]",
80                "async def foo(x):\n" +
81                "    await x\n" +
82                "    return 0\n" +
83                "\n" +
84                "def bar(y):\n" +
85                "    expr = foo(y)\n");
86       }
87     });
88   }
89
90   public void testAwaitCoroutine() {
91     runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() {
92       @Override
93       public void run() {
94         doTest("int",
95                "async def foo(x):\n" +
96                "    await x\n" +
97                "    return 0\n" +
98                "\n" +
99                "async def bar(y):\n" +
100                "    expr = await foo(y)\n");
101       }
102     });
103   }
104
105   // Not in PEP 484 as for now, see https://github.com/ambv/typehinting/issues/119
106   public void testCoroutineReturnTypeAnnotation() {
107     runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() {
108       @Override
109       public void run() {
110         doTest("int",
111                "async def foo() -> int: ...\n" +
112                "\n" +
113                "async def bar():\n" +
114                "    expr = await foo()\n");
115       }
116     });
117   }
118   
119   // PY-16987
120   public void testNoTypeInGoogleDocstringParamAnnotation() {
121     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
122       @Override
123       public void run() {
124         doTest("int", "def f(x: int):\n" +
125                       "    \"\"\"\n" +
126                       "    Args:\n" +
127                       "        x: foo\n" +
128                       "    \"\"\"    \n" +
129                       "    expr = x");
130       }
131     });
132   }
133   
134   // PY-16987
135   public void testUnfilledTypeInGoogleDocstringParamAnnotation() {
136     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
137       @Override
138       public void run() {
139         doTest("Any", "def f(x: int):\n" +
140                       "    \"\"\"\n" +
141                       "    Args:\n" +
142                       "        x (): foo\n" +
143                       "    \"\"\"    \n" +
144                       "    expr = x");
145       }
146     });
147   }
148   
149   // TODO: Same test for Numpy docstrings doesn't pass because typing provider is invoked earlier than NumpyDocStringTypeProvider
150   
151   // PY-16987
152   public void testNoTypeInNumpyDocstringParamAnnotation() {
153     runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
154       @Override
155       public void run() {
156         doTest("int", "def f(x: int):\n" +
157                       "    \"\"\"\n" +
158                       "    Parameters\n" +
159                       "    ----------\n" +
160                       "    x\n" +
161                       "        foo\n" +
162                       "    \"\"\"    \n" +
163                       "    expr = x");
164       }
165     });
166   }
167   
168   
169
170   private void doTest(final String expectedType, final String text) {
171     myFixture.configureByText(PythonFileType.INSTANCE, text);
172     final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
173     final TypeEvalContext context = TypeEvalContext.userInitiated(expr.getProject(), expr.getContainingFile()).withTracing();
174     final PyType actual = context.getType(expr);
175     final String actualType = PythonDocumentationProvider.getTypeName(actual, context);
176     assertEquals(expectedType, actualType);
177   }
178 }