diff --git a/python/psi-api/src/com/jetbrains/python/inspections/PyInspectionExtension.java b/python/psi-api/src/com/jetbrains/python/inspections/PyInspectionExtension.java
index f11618d72e60..74ee42db48e5 100644
--- a/python/psi-api/src/com/jetbrains/python/inspections/PyInspectionExtension.java
+++ b/python/psi-api/src/com/jetbrains/python/inspections/PyInspectionExtension.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -55,10 +55,32 @@ public abstract class PyInspectionExtension {
return false;
}
+ /**
+ * Checks if unresolved member could be ignored.
+ *
+ * @param type type whose member will be checked
+ * @param name member name
+ * @return true if the unresolved member with the specified name could be ignored
+ * @deprecated Use {@link PyInspectionExtension#ignoreUnresolvedMember(PyType, String, TypeEvalContext)} instead.
+ * This method will be removed in 2018.1.
+ */
+ @Deprecated
public boolean ignoreUnresolvedMember(@NotNull PyType type, @NotNull String name) {
return false;
}
+ /**
+ * Checks if unresolved member could be ignored.
+ *
+ * @param type type whose member will be checked
+ * @param name member name
+ * @param context type evaluation context
+ * @return true if the unresolved member with the specified name could be ignored
+ */
+ public boolean ignoreUnresolvedMember(@NotNull PyType type, @NotNull String name, @NotNull TypeEvalContext context) {
+ return ignoreUnresolvedMember(type, name);
+ }
+
/**
* Returns true if access to protected (the one started with "_") symbol should not be treated as violation.
*
diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml
index 8dc049e719f3..7af2fee357a4 100644
--- a/python/src/META-INF/python-core-common.xml
+++ b/python/src/META-INF/python-core-common.xml
@@ -690,6 +690,7 @@
+
diff --git a/python/src/com/jetbrains/python/codeInsight/typing/PyTypingInspectionExtension.kt b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingInspectionExtension.kt
new file mode 100644
index 000000000000..f958f584b029
--- /dev/null
+++ b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingInspectionExtension.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2017 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.codeInsight.typing
+
+import com.jetbrains.python.PyNames
+import com.jetbrains.python.inspections.PyInspectionExtension
+import com.jetbrains.python.psi.types.PyClassLikeType
+import com.jetbrains.python.psi.types.PyType
+import com.jetbrains.python.psi.types.TypeEvalContext
+
+class PyTypingInspectionExtension : PyInspectionExtension() {
+
+ override fun ignoreUnresolvedMember(type: PyType, name: String, context: TypeEvalContext): Boolean {
+ return name == PyNames.GETITEM && type is PyClassLikeType && type.isDefinition && isGenericItselfOrDescendant(type, context)
+ }
+
+ private fun isGenericItselfOrDescendant(type: PyClassLikeType,
+ context: TypeEvalContext): Boolean {
+ return type.classQName == PyTypingTypeProvider.GENERIC ||
+ type.getSuperClassTypes(context).any { it.classQName == PyTypingTypeProvider.GENERIC }
+ }
+}
+
diff --git a/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java
index f04a8869286e..6ee353183b47 100644
--- a/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/typing/PyTypingTypeProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -61,6 +61,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
public static final String ASYNC_GENERATOR = "typing.AsyncGenerator";
public static final String COROUTINE = "typing.Coroutine";
public static final String NAMEDTUPLE = "typing.NamedTuple";
+ public static final String GENERIC = "typing.Generic";
public static final Pattern TYPE_COMMENT_PATTERN = Pattern.compile("# *type: *(.*)");
@@ -80,7 +81,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
.build();
private static final ImmutableSet GENERIC_CLASSES = ImmutableSet.builder()
- .add("typing.Generic")
+ .add(GENERIC)
.add("typing.AbstractGeneric")
.add("typing.Protocol")
.build();
@@ -89,7 +90,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
.add("typing.overload")
.add("typing.Any")
.add("typing.TypeVar")
- .add("typing.Generic")
+ .add(GENERIC)
.add("typing.Tuple")
.add("typing.Callable")
.add("typing.Type")
@@ -107,7 +108,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
public PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context) {
// Check for the exact name in advance for performance reasons
if ("Generic".equals(referenceExpression.getName())) {
- if (resolveToQualifiedNames(referenceExpression, context).contains("typing.Generic")) {
+ if (resolveToQualifiedNames(referenceExpression, context).contains(GENERIC)) {
return createTypingGenericType();
}
}
@@ -219,7 +220,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
@NotNull
private static PyType createTypingGenericType() {
- return new PyCustomType("typing.Generic", null, false);
+ return new PyCustomType(GENERIC, null, false);
}
private static boolean omitFirstParamInTypeComment(@NotNull PyFunction func) {
@@ -304,7 +305,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
if (referenceTarget instanceof PyTargetExpression) {
final PyTargetExpression target = (PyTargetExpression)referenceTarget;
// Depends on typing.Generic defined as a target expression
- if ("typing.Generic".equals(target.getQualifiedName())) {
+ if (GENERIC.equals(target.getQualifiedName())) {
return createTypingGenericType();
}
if (context.maySwitchToAST(target)) {
diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
index 5bcec2e4273f..e5e6b0293243 100644
--- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -812,7 +812,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
}
}
for (PyInspectionExtension extension : Extensions.getExtensions(PyInspectionExtension.EP_NAME)) {
- if (extension.ignoreUnresolvedMember(type, name)) {
+ if (extension.ignoreUnresolvedMember(type, name, myTypeEvalContext)) {
return true;
}
}
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingGenericDunderGetItem.py b/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingGenericDunderGetItem.py
new file mode 100644
index 000000000000..028a98449049
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingGenericDunderGetItem.py
@@ -0,0 +1,4 @@
+import typing
+
+class MyClass(typing.Generic[str]):
+ pass
\ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingIterableDunderGetItem.py b/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingIterableDunderGetItem.py
new file mode 100644
index 000000000000..561367e4c950
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection3K/typingIterableDunderGetItem.py
@@ -0,0 +1,5 @@
+import typing
+
+
+def myfunc(seq: typing.Iterable[str]):
+ pass
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java
index 3b707ae9c67c..034911607a39 100644
--- a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -195,4 +195,14 @@ public class Py3UnresolvedReferencesInspectionTest extends PyTestCase {
public void testMockPatchObject() {
doMultiFileTest(getTestName(true) + ".py");
}
+
+ // PY-22525
+ public void testTypingIterableDunderGetItem() {
+ doTest();
+ }
+
+ // PY-22642
+ public void testTypingGenericDunderGetItem() {
+ doTest();
+ }
}