diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index 95f8408722ba..f687a0147188 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -3,6 +3,8 @@ package com.jetbrains.python.psi.types; import com.jetbrains.python.psi.PyClass; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * @author vlan */ @@ -22,8 +24,14 @@ public class PyTypeChecker { return match(expected, ((PyTypeReference)actual).resolve(null, context), context); } if (actual instanceof PyUnionType) { - for (PyType t : ((PyUnionType)actual).getMembers()) { - if (!match(expected, t, context)) { + final List members = ((PyUnionType)actual).getMembers(); + for (PyType m : members) { + if (m == null) { + return true; + } + } + for (PyType m : members) { + if (!match(expected, m, context)) { return false; } } diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeParser.java b/python/src/com/jetbrains/python/psi/types/PyTypeParser.java index d541496f1cc6..83fd47d9c3de 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeParser.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeParser.java @@ -237,9 +237,7 @@ public class PyTypeParser { PyType result = null; for (TextRange range : ranges) { final PyType t = parse(anchor, range.substring(type), types, fullRanges, offset + range.getStartOffset()); - if (t != null) { - result = (result == null) ? t : PyUnionType.union(result, t); - } + result = (result == null) ? t : PyUnionType.union(result, t); } return result; } diff --git a/python/src/com/jetbrains/python/refactoring/PyDefUseUtil.java b/python/src/com/jetbrains/python/refactoring/PyDefUseUtil.java index 6ebdfb0c79be..e2539f44c9d6 100644 --- a/python/src/com/jetbrains/python/refactoring/PyDefUseUtil.java +++ b/python/src/com/jetbrains/python/refactoring/PyDefUseUtil.java @@ -33,21 +33,9 @@ public class PyDefUseUtil { throw new InstructionNotFoundException(); } final boolean[] visited = new boolean[instructions.length]; - final Collection result = new HashSet(); + final Collection result = new LinkedHashSet(); getLatestDefs(var, instructions, instr, visited, result); - final List sortedResult = new ArrayList(); - sortedResult.addAll(result); - Collections.sort(sortedResult, new Comparator() { - @Override - public int compare(PyElement e1, PyElement e2) { - final String n1 = e1.getName(); - if (n1 != null) { - return n1.compareTo(e2.getName()); - } - return 0; - } - }); - return sortedResult.toArray(new PyElement[sortedResult.size()]); + return result.toArray(new PyElement[result.size()]); } private static void getLatestDefs(final PyElement var, diff --git a/python/testData/inspections/PyTypeCheckerInspection/test.py b/python/testData/inspections/PyTypeCheckerInspection/test.py index e1111cb9740c..b49e4b8cc137 100644 --- a/python/testData/inspections/PyTypeCheckerInspection/test.py +++ b/python/testData/inspections/PyTypeCheckerInspection/test.py @@ -220,4 +220,65 @@ def test_old_style_classes(): :type x: object """ pass - f(C()) #pass \ No newline at end of file + f(C()) #pass + + +def test_partly_unknown_type(): + def f(): + """ + :rtype: None or unknown or int or long + """ + def g(x): + """ + :type x: object + """ + g(f()) + + +def test_type_assertions(): + def f_1(): + """ + :rtype: int or str or None + """ + def f_2(): + """ + :rtype: int or None + """ + def f_3(): + """ + :rtype: unknown + """ + def f_4(): + """ + :rtype: object + """ + def f_5(): + """ + :rtype: int or object + """ + def f_6(): + """ + :rtype: int or unknown or float + """ + def f_7(): + """ + :rtype: int or unknown + """ + def print_int(x): + """ + :type x: int + """ + print(x) + def print_int_or_str(x): + """ + :type x: int or str + """ + x_1 = f_1() + print_int(x_1) + print_int_or_str(x_1) + if isinstance(x_1, int): + print_int(x_1) + if isinstance(x_1, str): + print_int_or_str(x_1) + x_7 = f_7() + print_int(x_7) \ No newline at end of file diff --git a/python/testData/quickdoc/Variable.html b/python/testData/quickdoc/Variable.html new file mode 100644 index 000000000000..3b9fee740875 --- /dev/null +++ b/python/testData/quickdoc/Variable.html @@ -0,0 +1 @@ +Assigned to y

Inferred type: one of (str, int)
\ No newline at end of file diff --git a/python/testData/quickdoc/Variable.py b/python/testData/quickdoc/Variable.py new file mode 100644 index 000000000000..9fdac0d1b811 --- /dev/null +++ b/python/testData/quickdoc/Variable.py @@ -0,0 +1,6 @@ +def f(x): + if x: + y = 1 + else: + y = 'foo' + return y \ No newline at end of file