Don't inspect protocol attributes inherited from non-protocols (PY-28720)

This commit is contained in:
Semyon Proshev
2018-03-16 21:47:20 +03:00
parent f0cd488478
commit b4c21038f3
2 changed files with 52 additions and 2 deletions
@@ -1,11 +1,11 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.codeInsight.typing
import com.intellij.openapi.util.io.FileUtil
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider.PROTOCOL_EXT
import com.jetbrains.python.psi.AccessDirection
import com.jetbrains.python.psi.PyClass
import com.jetbrains.python.psi.PyPossibleClassMember
import com.jetbrains.python.psi.PyTypedElement
import com.jetbrains.python.psi.resolve.PyResolveContext
import com.jetbrains.python.psi.resolve.RatedResolveResult
@@ -35,7 +35,14 @@ fun inspectProtocolSubclass(protocol: PyClassType, subclass: PyClassType, contex
protocol.toInstance().visitMembers(
{ e ->
if (e is PyTypedElement && FileUtil.getNameWithoutExtension(e.containingFile.name) != "typing_extensions") {
if (e is PyTypedElement) {
if (e is PyPossibleClassMember) {
val cls = e.containingClass
if (cls != null && !isProtocol(cls, context)) {
return@visitMembers true
}
}
val name = e.name ?: return@visitMembers true
val resolveResults = subclassAsInstance.resolveMember(name, null, AccessDirection.READ, resolveContext)
@@ -521,6 +521,49 @@ public class PyTypeCheckerInspectionTest extends PyInspectionTestCase {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);
}
// PY-28720
public void testOverriddenBuiltinMethodAgainstTypingProtocol() {
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() ->
doTestByText("import typing\n" +
"class Proto(typing.Protocol):\n" +
" def function(self) -> None:\n" +
" pass\n" +
"class Cls:\n" +
" def __eq__(self, other) -> 'Cls':\n" +
" pass\n" +
" def function(self) -> None:\n" +
" pass\n" +
"def method(p: Proto):\n" +
" pass\n" +
"method(Cls())")
);
}
// PY-28720
public void testAgainstInvalidProtocol() {
runWithLanguageLevel(
LanguageLevel.PYTHON34,
() ->
doTestByText(
"from typing import Any, Protocol\n" +
"class B:\n" +
" def foo(self):\n" +
" ...\n" +
"class C(B, Protocol):\n" +
" def bar(self):\n" +
" ...\n" +
"class Bar:\n" +
" def bar(self):\n" +
" ...\n" +
"def f(x: C) -> Any:\n" +
" ...\n" +
"f(Bar())"
)
);
}
// PY-23161
public void testGenericWithTypeVarBounds() {
runWithLanguageLevel(LanguageLevel.PYTHON35, this::doTest);